cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

libtelnet.h (21426B)


      1/*!
      2 * \brief libtelnet - TELNET protocol handling library
      3 *
      4 * SUMMARY:
      5 *
      6 * libtelnet is a library for handling the TELNET protocol.  It includes
      7 * routines for parsing incoming data from a remote peer as well as formatting
      8 * data to send to the remote peer.
      9 *
     10 * libtelnet uses a callback-oriented API, allowing application-specific
     11 * handling of various events.  The callback system is also used for buffering
     12 * outgoing protocol data, allowing the application to maintain control over
     13 * the actual socket connection.
     14 *
     15 * Features supported include the full TELNET protocol, Q-method option
     16 * negotiation, ZMP, MCCP2, MSSP, and NEW-ENVIRON.
     17 *
     18 * CONFORMS TO:
     19 *
     20 * RFC854  - http://www.faqs.org/rfcs/rfc854.html
     21 * RFC855  - http://www.faqs.org/rfcs/rfc855.html
     22 * RFC1091 - http://www.faqs.org/rfcs/rfc1091.html
     23 * RFC1143 - http://www.faqs.org/rfcs/rfc1143.html
     24 * RFC1408 - http://www.faqs.org/rfcs/rfc1408.html
     25 * RFC1572 - http://www.faqs.org/rfcs/rfc1572.html
     26 *
     27 * LICENSE:
     28 *
     29 * The author or authors of this code dedicate any and all copyright interest
     30 * in this code to the public domain. We make this dedication for the benefit
     31 * of the public at large and to the detriment of our heirs and successors. We
     32 * intend this dedication to be an overt act of relinquishment in perpetuity of
     33 * all present and future rights to this code under copyright law.
     34 *
     35 * \file libtelnet.h
     36 *
     37 * \version 0.23
     38 *
     39 * \author Sean Middleditch <sean@sourcemud.org>
     40 */
     41
     42#if !defined(LIBTELNET_INCLUDE)
     43#define LIBTELNET_INCLUDE 1
     44
     45/* standard C headers necessary for the libtelnet API */
     46#include <stdarg.h>
     47#include <stddef.h>
     48
     49/* C++ support */
     50#if defined(__cplusplus)
     51extern "C" {
     52#endif
     53
     54/* printf type checking feature in GCC and some other compilers */
     55#if __GNUC__
     56# define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a))) /*!< internal helper */
     57# define TELNET_GNU_SENTINEL __attribute__((sentinel)) /*!< internal helper */
     58#else
     59# define TELNET_GNU_PRINTF(f,a) /*!< internal helper */
     60# define TELNET_GNU_SENTINEL /*!< internal helper */
     61#endif
     62
     63/* Disable environ macro for Visual C++ 2015. */
     64#undef environ
     65
     66/*! Telnet state tracker object type. */
     67typedef struct telnet_t telnet_t;
     68
     69/*! Telnet event object type. */
     70typedef union telnet_event_t telnet_event_t;
     71
     72/*! Telnet option table element type. */
     73typedef struct telnet_telopt_t telnet_telopt_t;
     74
     75/*! \name Telnet commands */
     76/*@{*/
     77/*! Telnet commands and special values. */
     78#define TELNET_IAC 255
     79#define TELNET_DONT 254
     80#define TELNET_DO 253
     81#define TELNET_WONT 252
     82#define TELNET_WILL 251
     83#define TELNET_SB 250
     84#define TELNET_GA 249
     85#define TELNET_EL 248
     86#define TELNET_EC 247
     87#define TELNET_AYT 246
     88#define TELNET_AO 245
     89#define TELNET_IP 244
     90#define TELNET_BREAK 243
     91#define TELNET_DM 242
     92#define TELNET_NOP 241
     93#define TELNET_SE 240
     94#define TELNET_EOR 239
     95#define TELNET_ABORT 238
     96#define TELNET_SUSP 237
     97#define TELNET_EOF 236
     98/*@}*/
     99
    100/*! \name Telnet option values. */
    101/*@{*/
    102/*! Telnet options. */
    103#define TELNET_TELOPT_BINARY 0
    104#define TELNET_TELOPT_ECHO 1
    105#define TELNET_TELOPT_RCP 2
    106#define TELNET_TELOPT_SGA 3
    107#define TELNET_TELOPT_NAMS 4
    108#define TELNET_TELOPT_STATUS 5
    109#define TELNET_TELOPT_TM 6
    110#define TELNET_TELOPT_RCTE 7
    111#define TELNET_TELOPT_NAOL 8
    112#define TELNET_TELOPT_NAOP 9
    113#define TELNET_TELOPT_NAOCRD 10
    114#define TELNET_TELOPT_NAOHTS 11
    115#define TELNET_TELOPT_NAOHTD 12
    116#define TELNET_TELOPT_NAOFFD 13
    117#define TELNET_TELOPT_NAOVTS 14
    118#define TELNET_TELOPT_NAOVTD 15
    119#define TELNET_TELOPT_NAOLFD 16
    120#define TELNET_TELOPT_XASCII 17
    121#define TELNET_TELOPT_LOGOUT 18
    122#define TELNET_TELOPT_BM 19
    123#define TELNET_TELOPT_DET 20
    124#define TELNET_TELOPT_SUPDUP 21
    125#define TELNET_TELOPT_SUPDUPOUTPUT 22
    126#define TELNET_TELOPT_SNDLOC 23
    127#define TELNET_TELOPT_TTYPE 24
    128#define TELNET_TELOPT_EOR 25
    129#define TELNET_TELOPT_TUID 26
    130#define TELNET_TELOPT_OUTMRK 27
    131#define TELNET_TELOPT_TTYLOC 28
    132#define TELNET_TELOPT_3270REGIME 29
    133#define TELNET_TELOPT_X3PAD 30
    134#define TELNET_TELOPT_NAWS 31
    135#define TELNET_TELOPT_TSPEED 32
    136#define TELNET_TELOPT_LFLOW 33
    137#define TELNET_TELOPT_LINEMODE 34
    138#define TELNET_TELOPT_XDISPLOC 35
    139#define TELNET_TELOPT_ENVIRON 36
    140#define TELNET_TELOPT_AUTHENTICATION 37
    141#define TELNET_TELOPT_ENCRYPT 38
    142#define TELNET_TELOPT_NEW_ENVIRON 39
    143#define TELNET_TELOPT_MSSP 70
    144#define TELNET_TELOPT_COMPRESS 85
    145#define TELNET_TELOPT_COMPRESS2 86
    146#define TELNET_TELOPT_ZMP 93
    147#define TELNET_TELOPT_EXOPL 255
    148
    149#define TELNET_TELOPT_MCCP2 86
    150/*@}*/
    151
    152/*! \name Protocol codes for TERMINAL-TYPE commands. */
    153/*@{*/
    154/*! TERMINAL-TYPE codes. */
    155#define TELNET_TTYPE_IS 0
    156#define TELNET_TTYPE_SEND 1
    157/*@}*/
    158
    159/*! \name Protocol codes for NEW-ENVIRON/ENVIRON commands. */
    160/*@{*/
    161/*! NEW-ENVIRON/ENVIRON codes. */
    162#define TELNET_ENVIRON_IS 0
    163#define TELNET_ENVIRON_SEND 1
    164#define TELNET_ENVIRON_INFO 2
    165#define TELNET_ENVIRON_VAR 0
    166#define TELNET_ENVIRON_VALUE 1
    167#define TELNET_ENVIRON_ESC 2
    168#define TELNET_ENVIRON_USERVAR 3
    169/*@}*/
    170
    171/*! \name Protocol codes for MSSP commands. */
    172/*@{*/
    173/*! MSSP codes. */
    174#define TELNET_MSSP_VAR 1
    175#define TELNET_MSSP_VAL 2
    176/*@}*/
    177
    178/*! \name Telnet state tracker flags. */
    179/*@{*/
    180/*! Control behavior of telnet state tracker. */
    181#define TELNET_FLAG_PROXY (1<<0)
    182#define TELNET_FLAG_NVT_EOL (1<<1)
    183
    184/* Internal-only bits in option flags */
    185#define TELNET_FLAG_TRANSMIT_BINARY (1<<5)
    186#define TELNET_FLAG_RECEIVE_BINARY (1<<6)
    187#define TELNET_PFLAG_DEFLATE (1<<7)
    188/*@}*/
    189
    190/*! 
    191 * error codes 
    192 */
    193enum telnet_error_t {
    194	TELNET_EOK = 0,   /*!< no error */
    195	TELNET_EBADVAL,   /*!< invalid parameter, or API misuse */
    196	TELNET_ENOMEM,    /*!< memory allocation failure */
    197	TELNET_EOVERFLOW, /*!< data exceeds buffer size */
    198	TELNET_EPROTOCOL, /*!< invalid sequence of special bytes */
    199	TELNET_ECOMPRESS  /*!< error handling compressed streams */
    200};
    201typedef enum telnet_error_t telnet_error_t; /*!< Error code type. */
    202
    203/*! 
    204 * event codes 
    205 */
    206enum telnet_event_type_t {
    207	TELNET_EV_DATA = 0,        /*!< raw text data has been received */
    208	TELNET_EV_SEND,            /*!< data needs to be sent to the peer */
    209	TELNET_EV_IAC,             /*!< generic IAC code received */
    210	TELNET_EV_WILL,            /*!< WILL option negotiation received */
    211	TELNET_EV_WONT,            /*!< WONT option neogitation received */
    212	TELNET_EV_DO,              /*!< DO option negotiation received */
    213	TELNET_EV_DONT,            /*!< DONT option negotiation received */
    214	TELNET_EV_SUBNEGOTIATION,  /*!< sub-negotiation data received */
    215	TELNET_EV_COMPRESS,        /*!< compression has been enabled */
    216	TELNET_EV_ZMP,             /*!< ZMP command has been received */
    217	TELNET_EV_TTYPE,           /*!< TTYPE command has been received */
    218	TELNET_EV_ENVIRON,         /*!< ENVIRON command has been received */
    219	TELNET_EV_MSSP,            /*!< MSSP command has been received */
    220	TELNET_EV_WARNING,         /*!< recoverable error has occured */
    221	TELNET_EV_ERROR            /*!< non-recoverable error has occured */
    222};
    223typedef enum telnet_event_type_t telnet_event_type_t; /*!< Telnet event type. */
    224
    225/*! 
    226 * environ/MSSP command information 
    227 */
    228struct telnet_environ_t {
    229	unsigned char type; /*!< either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR */
    230	char *var;          /*!< name of the variable being set */
    231	char *value;        /*!< value of variable being set; empty string if no value */
    232};
    233
    234/*! 
    235 * event information 
    236 */
    237union telnet_event_t {
    238	/*! 
    239	 * \brief Event type
    240	 *
    241	 * The type field will determine which of the other event structure fields
    242	 * have been filled in.  For instance, if the event type is TELNET_EV_ZMP,
    243	 * then the zmp event field (and ONLY the zmp event field) will be filled
    244	 * in.
    245	 */ 
    246	enum telnet_event_type_t type;
    247
    248	/*! 
    249	 * data event: for DATA and SEND events 
    250	 */
    251	struct data_t {
    252		enum telnet_event_type_t _type; /*!< alias for type */
    253		const char *buffer;             /*!< byte buffer */
    254		size_t size;                    /*!< number of bytes in buffer */
    255	} data;
    256
    257	/*! 
    258	 * WARNING and ERROR events 
    259	 */
    260	struct error_t {
    261		enum telnet_event_type_t _type; /*!< alias for type */
    262		const char *file;               /*!< file the error occured in */
    263		const char *func;               /*!< function the error occured in */
    264		const char *msg;                /*!< error message string */
    265		int line;                       /*!< line of file error occured on */
    266		telnet_error_t errcode;         /*!< error code */
    267	} error;
    268
    269	/*! 
    270	 * command event: for IAC 
    271	 */
    272	struct iac_t {
    273		enum telnet_event_type_t _type; /*!< alias for type */
    274		unsigned char cmd;              /*!< telnet command received */
    275	} iac;
    276
    277	/*! 
    278	 * negotiation event: WILL, WONT, DO, DONT 
    279	 */
    280	struct negotiate_t {
    281		enum telnet_event_type_t _type; /*!< alias for type */
    282		unsigned char telopt;           /*!< option being negotiated */
    283	} neg;
    284
    285	/*! 
    286	 * subnegotiation event 
    287	 */
    288	struct subnegotiate_t {
    289		enum telnet_event_type_t _type; /*!< alias for type */
    290		const char *buffer;             /*!< data of sub-negotiation */
    291		size_t size;                    /*!< number of bytes in buffer */
    292		unsigned char telopt;           /*!< option code for negotiation */
    293	} sub;
    294
    295	/*! 
    296	 * ZMP event 
    297	 */
    298	struct zmp_t {
    299		enum telnet_event_type_t _type; /*!< alias for type */
    300		const char **argv;              /*!< array of argument string */
    301		size_t argc;                    /*!< number of elements in argv */
    302	} zmp;
    303
    304	/*! 
    305	 * TTYPE event 
    306	 */
    307	struct ttype_t {
    308		enum telnet_event_type_t _type; /*!< alias for type */
    309		unsigned char cmd;              /*!< TELNET_TTYPE_IS or TELNET_TTYPE_SEND */
    310		const char* name;               /*!< terminal type name (IS only) */
    311	} ttype;
    312
    313	/*! 
    314	 * COMPRESS event 
    315	 */
    316	struct compress_t {
    317		enum telnet_event_type_t _type; /*!< alias for type */
    318		unsigned char state;            /*!< 1 if compression is enabled,
    319	                                         0 if disabled */
    320	} compress;
    321
    322	/*! 
    323	 * ENVIRON/NEW-ENVIRON event
    324	 */
    325	struct environ_t {
    326		enum telnet_event_type_t _type;        /*!< alias for type */
    327		const struct telnet_environ_t *values; /*!< array of variable values */
    328		size_t size;                           /*!< number of elements in values */
    329		unsigned char cmd;                     /*!< SEND, IS, or INFO */
    330	} environ;
    331	
    332	/*!
    333	 * MSSP event
    334	 */
    335	struct mssp_t {
    336		enum telnet_event_type_t _type;        /*!< alias for type */
    337		const struct telnet_environ_t *values; /*!< array of variable values */
    338		size_t size;                           /*!< number of elements in values */
    339	} mssp;
    340};
    341
    342/*! 
    343 * \brief event handler
    344 *
    345 * This is the type of function that must be passed to
    346 * telnet_init() when creating a new telnet object.  The
    347 * function will be invoked once for every event generated
    348 * by the libtelnet protocol parser.
    349 *
    350 * \param telnet    The telnet object that generated the event
    351 * \param event     Event structure with details about the event
    352 * \param user_data User-supplied pointer
    353 */
    354typedef void (*telnet_event_handler_t)(telnet_t *telnet,
    355		telnet_event_t *event, void *user_data);
    356
    357/*! 
    358 * telopt support table element; use telopt of -1 for end marker 
    359 */
    360struct telnet_telopt_t {
    361	short telopt;      /*!< one of the TELOPT codes or -1 */
    362	unsigned char us;  /*!< TELNET_WILL or TELNET_WONT */
    363	unsigned char him; /*!< TELNET_DO or TELNET_DONT */
    364};
    365
    366/*! 
    367 * state tracker -- private data structure 
    368 */
    369struct telnet_t;
    370
    371/*!
    372 * \brief Initialize a telnet state tracker.
    373 *
    374 * This function initializes a new state tracker, which is used for all
    375 * other libtelnet functions.  Each connection must have its own
    376 * telnet state tracker object.
    377 *
    378 * \param telopts   Table of TELNET options the application supports.
    379 * \param eh        Event handler function called for every event.
    380 * \param flags     0 or TELNET_FLAG_PROXY.
    381 * \param user_data Optional data pointer that will be passsed to eh.
    382 * \return Telnet state tracker object.
    383 */
    384extern telnet_t* telnet_init(const telnet_telopt_t *telopts,
    385		telnet_event_handler_t eh, unsigned char flags, void *user_data);
    386
    387/*!
    388 * \brief Free up any memory allocated by a state tracker.
    389 *
    390 * This function must be called when a telnet state tracker is no
    391 * longer needed (such as after the connection has been closed) to
    392 * release any memory resources used by the state tracker.
    393 *
    394 * \param telnet Telnet state tracker object.
    395 */
    396extern void telnet_free(telnet_t *telnet);
    397
    398/*!
    399 * \brief Push a byte buffer into the state tracker.
    400 *
    401 * Passes one or more bytes to the telnet state tracker for
    402 * protocol parsing.  The byte buffer is most often going to be
    403 * the buffer that recv() was called for while handling the
    404 * connection.
    405 *
    406 * \param telnet Telnet state tracker object.
    407 * \param buffer Pointer to byte buffer.
    408 * \param size   Number of bytes pointed to by buffer.
    409 */
    410extern void telnet_recv(telnet_t *telnet, const char *buffer,
    411		size_t size);
    412
    413/*!
    414 * \brief Send a telnet command.
    415 *
    416 * \param telnet Telnet state tracker object.
    417 * \param cmd    Command to send.
    418 */
    419extern void telnet_iac(telnet_t *telnet, unsigned char cmd);
    420
    421/*!
    422 * \brief Send negotiation command.
    423 *
    424 * Internally, libtelnet uses RFC1143 option negotiation rules.
    425 * The negotiation commands sent with this function may be ignored
    426 * if they are determined to be redundant.
    427 *
    428 * \param telnet Telnet state tracker object.
    429 * \param cmd    TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT.
    430 * \param opt    One of the TELNET_TELOPT_* values.
    431 */
    432extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
    433		unsigned char opt);
    434
    435/*!
    436 * Send non-command data (escapes IAC bytes).
    437 *
    438 * \param telnet Telnet state tracker object.
    439 * \param buffer Buffer of bytes to send.
    440 * \param size   Number of bytes to send.
    441 */
    442extern void telnet_send(telnet_t *telnet,
    443		const char *buffer, size_t size);
    444
    445/*!
    446 * Send non-command text (escapes IAC bytes and translates
    447 * \\r -> CR-NUL and \\n -> CR-LF unless in BINARY mode.
    448 *
    449 * \param telnet Telnet state tracker object.
    450 * \param buffer Buffer of bytes to send.
    451 * \param size   Number of bytes to send.
    452 */
    453extern void telnet_send_text(telnet_t *telnet,
    454		const char *buffer, size_t size);
    455
    456/*!
    457 * \brief Begin a sub-negotiation command.
    458 *
    459 * Sends IAC SB followed by the telopt code.  All following data sent
    460 * will be part of the sub-negotiation, until telnet_finish_sb() is
    461 * called.
    462 *
    463 * \param telnet Telnet state tracker object.
    464 * \param telopt One of the TELNET_TELOPT_* values.
    465 */
    466extern void telnet_begin_sb(telnet_t *telnet,
    467		unsigned char telopt);
    468
    469/*!
    470 * \brief Finish a sub-negotiation command.
    471 *
    472 * This must be called after a call to telnet_begin_sb() to finish a
    473 * sub-negotiation command.
    474 *
    475 * \param telnet Telnet state tracker object.
    476 */
    477#define telnet_finish_sb(telnet) telnet_iac((telnet), TELNET_SE)
    478
    479/*!
    480 * \brief Shortcut for sending a complete subnegotiation buffer.
    481 *
    482 * Equivalent to:
    483 *   telnet_begin_sb(telnet, telopt);
    484 *   telnet_send(telnet, buffer, size);
    485 *   telnet_finish_sb(telnet);
    486 *
    487 * \param telnet Telnet state tracker format.
    488 * \param telopt One of the TELNET_TELOPT_* values.
    489 * \param buffer Byte buffer for sub-negotiation data.
    490 * \param size   Number of bytes to use for sub-negotiation data.
    491 */
    492extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt,
    493		const char *buffer, size_t size);
    494
    495/*!
    496 * \brief Begin sending compressed data.
    497 *
    498 * This function will begein sending data using the COMPRESS2 option,
    499 * which enables the use of zlib to compress data sent to the client.
    500 * The client must offer support for COMPRESS2 with option negotiation,
    501 * and zlib support must be compiled into libtelnet.
    502 *
    503 * Only the server may call this command.
    504 *
    505 * \param telnet Telnet state tracker object.
    506 */
    507extern void telnet_begin_compress2(telnet_t *telnet);
    508
    509/*!
    510 * \brief Send formatted data.
    511 *
    512 * This function is a wrapper around telnet_send().  It allows using
    513 * printf-style formatting.
    514 *
    515 * Additionally, this function will translate \\r to the CR NUL construct and
    516 * \\n with CR LF, as well as automatically escaping IAC bytes like
    517 * telnet_send().
    518 *
    519 * \param telnet Telnet state tracker object.
    520 * \param fmt    Format string.
    521 * \return Number of bytes sent.
    522 */
    523extern int telnet_printf(telnet_t *telnet, const char *fmt, ...)
    524		TELNET_GNU_PRINTF(2, 3);
    525
    526/*!
    527 * \brief Send formatted data.
    528 *
    529 * See telnet_printf().
    530 */
    531extern int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va);
    532
    533/*!
    534 * \brief Send formatted data (no newline escaping).
    535 *
    536 * This behaves identically to telnet_printf(), except that the \\r and \\n
    537 * characters are not translated.  The IAC byte is still escaped as normal
    538 * with telnet_send().
    539 *
    540 * \param telnet Telnet state tracker object.
    541 * \param fmt    Format string.
    542 * \return Number of bytes sent.
    543 */
    544extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...)
    545		TELNET_GNU_PRINTF(2, 3);
    546
    547/*!
    548 * \brief Send formatted data (no newline escaping).
    549 *
    550 * See telnet_raw_printf().
    551 */
    552extern int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va);
    553
    554/*!
    555 * \brief Begin a new set of NEW-ENVIRON values to request or send.
    556 *
    557 * This function will begin the sub-negotiation block for sending or
    558 * requesting NEW-ENVIRON values.
    559 *
    560 * The telnet_finish_newenviron() macro must be called after this
    561 * function to terminate the NEW-ENVIRON command.
    562 *
    563 * \param telnet Telnet state tracker object.
    564 * \param type   One of TELNET_ENVIRON_SEND, TELNET_ENVIRON_IS, or
    565 *               TELNET_ENVIRON_INFO.
    566 */
    567extern void telnet_begin_newenviron(telnet_t *telnet, unsigned char type);
    568
    569/*!
    570 * \brief Send a NEW-ENVIRON variable name or value.
    571 *
    572 * This can only be called between calls to telnet_begin_newenviron() and
    573 * telnet_finish_newenviron().
    574 *
    575 * \param telnet Telnet state tracker object.
    576 * \param type   One of TELNET_ENVIRON_VAR, TELNET_ENVIRON_USERVAR, or
    577 *               TELNET_ENVIRON_VALUE.
    578 * \param string Variable name or value.
    579 */
    580extern void telnet_newenviron_value(telnet_t* telnet, unsigned char type,
    581		const char *string);
    582
    583/*!
    584 * \brief Finish a NEW-ENVIRON command.
    585 *
    586 * This must be called after a call to telnet_begin_newenviron() to finish a
    587 * NEW-ENVIRON variable list.
    588 *
    589 * \param telnet Telnet state tracker object.
    590 */
    591#define telnet_finish_newenviron(telnet) telnet_finish_sb((telnet))
    592
    593/*!
    594 * \brief Send the TERMINAL-TYPE SEND command.
    595 *
    596 * Sends the sequence IAC TERMINAL-TYPE SEND.
    597 *
    598 * \param telnet Telnet state tracker object.
    599 */
    600extern void telnet_ttype_send(telnet_t *telnet);
    601
    602/*!
    603 * \brief Send the TERMINAL-TYPE IS command.
    604 *
    605 * Sends the sequence IAC TERMINAL-TYPE IS "string".
    606 *
    607 * According to the RFC, the recipient of a TERMINAL-TYPE SEND shall
    608 * send the next possible terminal-type the client supports.  Upon sending
    609 * the type, the client should switch modes to begin acting as the terminal
    610 * type is just sent.
    611 *
    612 * The server may continue sending TERMINAL-TYPE IS until it receives a
    613 * terminal type is understands.  To indicate to the server that it has
    614 * reached the end of the available optoins, the client must send the last
    615 * terminal type a second time.  When the server receives the same terminal
    616 * type twice in a row, it knows it has seen all available terminal types.
    617 *
    618 * After the last terminal type is sent, if the client receives another
    619 * TERMINAL-TYPE SEND command, it must begin enumerating the available
    620 * terminal types from the very beginning.  This allows the server to
    621 * scan the available types for a preferred terminal type and, if none
    622 * is found, to then ask the client to switch to an acceptable
    623 * alternative.
    624 *
    625 * Note that if the client only supports a single terminal type, then
    626 * simply sending that one type in response to every SEND will satisfy
    627 * the behavior requirements.
    628 *
    629 * \param telnet Telnet state tracker object.
    630 * \param ttype  Name of the terminal-type being sent.
    631 */
    632extern void telnet_ttype_is(telnet_t *telnet, const char* ttype);
    633
    634/*!
    635 * \brief Send a ZMP command.
    636 *
    637 * \param telnet Telnet state tracker object.
    638 * \param argc   Number of ZMP commands being sent.
    639 * \param argv   Array of argument strings.
    640 */
    641extern void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv);
    642
    643/*!
    644 * \brief Send a ZMP command.
    645 *
    646 * Arguments are listed out in var-args style.  After the last argument, a
    647 * NULL pointer must be passed in as a sentinel value.
    648 *
    649 * \param telnet Telnet state tracker object.
    650 */
    651extern void telnet_send_zmpv(telnet_t *telnet, ...) TELNET_GNU_SENTINEL;
    652
    653/*!
    654 * \brief Send a ZMP command.
    655 *
    656 * See telnet_send_zmpv().
    657 */
    658extern void telnet_send_vzmpv(telnet_t *telnet, va_list va);
    659
    660/*!
    661 * \brief Begin sending a ZMP command
    662 *
    663 * \param telnet Telnet state tracker object.
    664 * \param cmd    The first argument (command name) for the ZMP command.
    665 */
    666extern void telnet_begin_zmp(telnet_t *telnet, const char *cmd);
    667
    668/*!
    669 * \brief Send a ZMP command argument.
    670 *
    671 * \param telnet Telnet state tracker object.
    672 * \param arg    Telnet argument string.
    673 */
    674extern void telnet_zmp_arg(telnet_t *telnet, const char *arg);
    675
    676/*!
    677 * \brief Finish a ZMP command.
    678 *
    679 * This must be called after a call to telnet_begin_zmp() to finish a
    680 * ZMP argument list.
    681 *
    682 * \param telnet Telnet state tracker object.
    683 */
    684#define telnet_finish_zmp(telnet) telnet_finish_sb((telnet))
    685
    686/* C++ support */
    687#if defined(__cplusplus)
    688} /* extern "C" */
    689#endif
    690
    691#endif /* !defined(LIBTELNET_INCLUDE) */