This commit is contained in:
commit
2e9289e936
|
@ -0,0 +1,76 @@
|
||||||
|
/** function comment
|
||||||
|
* @Author: 陈逸凡 1343619937@qq.com
|
||||||
|
* @Date: 2024-04-02 13:45:24
|
||||||
|
* @LastEditors: 陈逸凡 1343619937@qq.com
|
||||||
|
* @LastEditTime: 2024-04-23 09:52:30
|
||||||
|
* @FilePath: \com.quaero.soc.fluorescence\module\common\shell\inc\shell.h
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
/*- Coding With UTF-8 -*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* File Name: shell.h
|
||||||
|
* Description: 此文件提供了shell的相关配置,声明
|
||||||
|
* Atuhor: Letter
|
||||||
|
* Date: 2018/4/20
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __SHELL_H__
|
||||||
|
#define __SHELL_H__
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/*------------------------------宏定义----------------------------------------*/
|
||||||
|
#define SHELL_VERSION "v1.5" //版本
|
||||||
|
|
||||||
|
#define SHELL_USE_PARAMETER 1 //是否使用带参函数
|
||||||
|
#define SHELL_USE_HISTORY 1 //是否使用历史命令
|
||||||
|
|
||||||
|
//#define shellUart huart1 //shell使用的串口
|
||||||
|
|
||||||
|
#define SHELL_COMMAND_MAX_LENGTH 100 //shell命令最大长度
|
||||||
|
#define SHELL_PARAMETER_MAX_LENGTH 25 //shell命令参数最大长度
|
||||||
|
#define SHELL_PARAMETER_MAX_NUMBER 20 //shell命令参数最大数量
|
||||||
|
|
||||||
|
#define SHELL_HISTORY_MAX_NUMBER 5 //历史命令记录数量
|
||||||
|
|
||||||
|
#define SHELL_COMMAND "\r\n>>"
|
||||||
|
|
||||||
|
#define shellDisplay(x) _ShellDisplay((uint8_t *) (x));
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------函数指针定义-------------------------------------*/
|
||||||
|
typedef void (*shellFunction)(char *args);
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------结构体定义--------------------------------------*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *name; //shell命令名称
|
||||||
|
shellFunction function; //shell命令函数
|
||||||
|
const char *desc; //shell命令描述
|
||||||
|
}SHELL_CommandTypeDef; //shell命令定义
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CONTROL_FREE = 0,
|
||||||
|
CONTROL_STEP_ONE,
|
||||||
|
CONTROL_STEP_TWO,
|
||||||
|
}CONTROL_Status;
|
||||||
|
/*****************************internal function declare**********************/
|
||||||
|
#define isReadChar(a) ((a>='a'&& a<='z')||(a>='A'&&a<='Z')||(a>='0'&&a<='9'))
|
||||||
|
#define searchChar(a) {while(isReadChar(*a)==0){a++;}}
|
||||||
|
char *getArg(char *input, char *output);
|
||||||
|
float ana_float(char *arg);
|
||||||
|
#define PART_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
void shellShowCommandList(char *args); //显示所有shell命令
|
||||||
|
void shellLetter(char *args); //显示shell信息
|
||||||
|
void shellReboot(char *args); //重启系统
|
||||||
|
void shellClear(char *args); //shell清屏
|
||||||
|
|
||||||
|
extern void user_print(char *format, ...);
|
||||||
|
void key_handle(char *c);
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef _SHELLCMD_H
|
||||||
|
#define _SHELLCMD_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void shell_init(void);
|
||||||
|
// int32_t can_status(uint32_t argc, uint8_t *argv[]);
|
||||||
|
// int32_t show_net_node(uint32_t argc, uint8_t *argv[]);
|
||||||
|
// int32_t alloc_mem_total(uint32_t argc, uint8_t *argv[]);
|
||||||
|
/*-----------------------------函数声明---------------------------------------*/
|
||||||
|
void shellFunTest(char *args);
|
||||||
|
void can_status(char *args);
|
||||||
|
void show_net_node(char *args);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,449 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1983, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)telnet.h 8.2 (Berkeley) 12/15/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TELNET_H_
|
||||||
|
#define _TELNET_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for the TELNET protocol.
|
||||||
|
*/
|
||||||
|
#define IAC 255 /* interpret as command: */
|
||||||
|
#define DONT 254 /* you are not to use option */
|
||||||
|
#define DO 253 /* please, you use option */
|
||||||
|
#define WONT 252 /* I won't use option */
|
||||||
|
#define WILL 251 /* I will use option */
|
||||||
|
#define SB 250 /* interpret as subnegotiation */
|
||||||
|
#define GA 249 /* you may reverse the line */
|
||||||
|
#define EL 248 /* erase the current line */
|
||||||
|
#define EC 247 /* erase the current character */
|
||||||
|
#define AYT 246 /* are you there */
|
||||||
|
#define AO 245 /* abort output--but let prog finish */
|
||||||
|
#define IP 244 /* interrupt process--permanently */
|
||||||
|
#define BREAK 243 /* break */
|
||||||
|
#define DM 242 /* data mark--for connect. cleaning */
|
||||||
|
#define NOP 241 /* nop */
|
||||||
|
#define SE 240 /* end sub negotiation */
|
||||||
|
#define EOR 239 /* end of record (transparent mode) */
|
||||||
|
#define ABORT 238 /* Abort process */
|
||||||
|
#define SUSP 237 /* Suspend process */
|
||||||
|
#define xEOF 236 /* End of file: EOF is already used... */
|
||||||
|
|
||||||
|
#define SYNCH 242 /* for telfunc calls */
|
||||||
|
|
||||||
|
#ifdef TELCMDS
|
||||||
|
char *telcmds[] = {
|
||||||
|
"EOF",
|
||||||
|
"SUSP",
|
||||||
|
"ABORT",
|
||||||
|
"EOR",
|
||||||
|
"SE",
|
||||||
|
"NOP",
|
||||||
|
"DMARK",
|
||||||
|
"BRK",
|
||||||
|
"IP",
|
||||||
|
"AO",
|
||||||
|
"AYT",
|
||||||
|
"EC",
|
||||||
|
"EL",
|
||||||
|
"GA",
|
||||||
|
"SB",
|
||||||
|
"WILL",
|
||||||
|
"WONT",
|
||||||
|
"DO",
|
||||||
|
"DONT",
|
||||||
|
"IAC",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *telcmds[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TELCMD_FIRST xEOF
|
||||||
|
#define TELCMD_LAST IAC
|
||||||
|
#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
|
||||||
|
(unsigned int)(x) >= TELCMD_FIRST)
|
||||||
|
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
|
||||||
|
|
||||||
|
/* telnet options */
|
||||||
|
#define TELOPT_BINARY 0 /* 8-bit data path */
|
||||||
|
#define TELOPT_ECHO 1 /* echo */
|
||||||
|
#define TELOPT_RCP 2 /* prepare to reconnect */
|
||||||
|
#define TELOPT_SGA 3 /* suppress go ahead */
|
||||||
|
#define TELOPT_NAMS 4 /* approximate message size */
|
||||||
|
#define TELOPT_STATUS 5 /* give status */
|
||||||
|
#define TELOPT_TM 6 /* timing mark */
|
||||||
|
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
|
||||||
|
#define TELOPT_NAOL 8 /* negotiate about output line width */
|
||||||
|
#define TELOPT_NAOP 9 /* negotiate about output page size */
|
||||||
|
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
|
||||||
|
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
|
||||||
|
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
|
||||||
|
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
|
||||||
|
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
|
||||||
|
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
|
||||||
|
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
|
||||||
|
#define TELOPT_XASCII 17 /* extended ascic character set */
|
||||||
|
#define TELOPT_LOGOUT 18 /* force logout */
|
||||||
|
#define TELOPT_BM 19 /* byte macro */
|
||||||
|
#define TELOPT_DET 20 /* data entry terminal */
|
||||||
|
#define TELOPT_SUPDUP 21 /* supdup protocol */
|
||||||
|
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
|
||||||
|
#define TELOPT_SNDLOC 23 /* send location */
|
||||||
|
#define TELOPT_TTYPE 24 /* terminal type */
|
||||||
|
#define TELOPT_EOR 25 /* end or record */
|
||||||
|
#define TELOPT_TUID 26 /* TACACS user identification */
|
||||||
|
#define TELOPT_OUTMRK 27 /* output marking */
|
||||||
|
#define TELOPT_TTYLOC 28 /* terminal location number */
|
||||||
|
#define TELOPT_3270REGIME 29 /* 3270 regime */
|
||||||
|
#define TELOPT_X3PAD 30 /* X.3 PAD */
|
||||||
|
#define TELOPT_NAWS 31 /* window size */
|
||||||
|
#define TELOPT_TSPEED 32 /* terminal speed */
|
||||||
|
#define TELOPT_LFLOW 33 /* remote flow control */
|
||||||
|
#define TELOPT_LINEMODE 34 /* Linemode option */
|
||||||
|
#define TELOPT_XDISPLOC 35 /* X Display Location */
|
||||||
|
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
|
||||||
|
#define TELOPT_AUTHENTICATION 37 /* Authenticate */
|
||||||
|
#define TELOPT_ENCRYPT 38 /* Encryption option */
|
||||||
|
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
|
||||||
|
#define TELOPT_EXOPL 255 /* extended-options-list */
|
||||||
|
|
||||||
|
// #define TELOPTS
|
||||||
|
#define NTELOPTS (1 + TELOPT_NEW_ENVIRON)
|
||||||
|
#ifdef TELOPTS
|
||||||
|
char *telopts[NTELOPTS + 1] = {
|
||||||
|
"BINARY",
|
||||||
|
"ECHO",
|
||||||
|
"RCP",
|
||||||
|
"SUPPRESS GO AHEAD",
|
||||||
|
"NAME",
|
||||||
|
"STATUS",
|
||||||
|
"TIMING MARK",
|
||||||
|
"RCTE",
|
||||||
|
"NAOL",
|
||||||
|
"NAOP",
|
||||||
|
"NAOCRD",
|
||||||
|
"NAOHTS",
|
||||||
|
"NAOHTD",
|
||||||
|
"NAOFFD",
|
||||||
|
"NAOVTS",
|
||||||
|
"NAOVTD",
|
||||||
|
"NAOLFD",
|
||||||
|
"EXTEND ASCII",
|
||||||
|
"LOGOUT",
|
||||||
|
"BYTE MACRO",
|
||||||
|
"DATA ENTRY TERMINAL",
|
||||||
|
"SUPDUP",
|
||||||
|
"SUPDUP OUTPUT",
|
||||||
|
"SEND LOCATION",
|
||||||
|
"TERMINAL TYPE",
|
||||||
|
"END OF RECORD",
|
||||||
|
"TACACS UID",
|
||||||
|
"OUTPUT MARKING",
|
||||||
|
"TTYLOC",
|
||||||
|
"3270 REGIME",
|
||||||
|
"X.3 PAD",
|
||||||
|
"NAWS",
|
||||||
|
"TSPEED",
|
||||||
|
"LFLOW",
|
||||||
|
"LINEMODE",
|
||||||
|
"XDISPLOC",
|
||||||
|
"OLD-ENVIRON",
|
||||||
|
"AUTHENTICATION",
|
||||||
|
"ENCRYPT",
|
||||||
|
"NEW-ENVIRON",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
#define TELOPT_FIRST TELOPT_BINARY
|
||||||
|
#define TELOPT_LAST TELOPT_NEW_ENVIRON
|
||||||
|
#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
|
||||||
|
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sub-option qualifiers */
|
||||||
|
#define TELQUAL_IS 0 /* option is... */
|
||||||
|
#define TELQUAL_SEND 1 /* send option */
|
||||||
|
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
|
||||||
|
#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
|
||||||
|
#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
|
||||||
|
|
||||||
|
#define LFLOW_OFF 0 /* Disable remote flow control */
|
||||||
|
#define LFLOW_ON 1 /* Enable remote flow control */
|
||||||
|
#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
|
||||||
|
#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LINEMODE suboptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LM_MODE 1
|
||||||
|
#define LM_FORWARDMASK 2
|
||||||
|
#define LM_SLC 3
|
||||||
|
|
||||||
|
#define MODE_EDIT 0x01
|
||||||
|
#define MODE_TRAPSIG 0x02
|
||||||
|
#define MODE_ACK 0x04
|
||||||
|
#define MODE_SOFT_TAB 0x08
|
||||||
|
#define MODE_LIT_ECHO 0x10
|
||||||
|
|
||||||
|
#define MODE_MASK 0x1f
|
||||||
|
|
||||||
|
/* Not part of protocol, but needed to simplify things... */
|
||||||
|
#define MODE_FLOW 0x0100
|
||||||
|
#define MODE_ECHO 0x0200
|
||||||
|
#define MODE_INBIN 0x0400
|
||||||
|
#define MODE_OUTBIN 0x0800
|
||||||
|
#define MODE_FORCE 0x1000
|
||||||
|
|
||||||
|
#define SLC_SYNCH 1
|
||||||
|
#define SLC_BRK 2
|
||||||
|
#define SLC_IP 3
|
||||||
|
#define SLC_AO 4
|
||||||
|
#define SLC_AYT 5
|
||||||
|
#define SLC_EOR 6
|
||||||
|
#define SLC_ABORT 7
|
||||||
|
#define SLC_EOF 8
|
||||||
|
#define SLC_SUSP 9
|
||||||
|
#define SLC_EC 10
|
||||||
|
#define SLC_EL 11
|
||||||
|
#define SLC_EW 12
|
||||||
|
#define SLC_RP 13
|
||||||
|
#define SLC_LNEXT 14
|
||||||
|
#define SLC_XON 15
|
||||||
|
#define SLC_XOFF 16
|
||||||
|
#define SLC_FORW1 17
|
||||||
|
#define SLC_FORW2 18
|
||||||
|
|
||||||
|
#define NSLC 18
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For backwards compatability, we define SLC_NAMES to be the
|
||||||
|
* list of names if SLC_NAMES is not defined.
|
||||||
|
*/
|
||||||
|
#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
|
||||||
|
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
|
||||||
|
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
|
||||||
|
#ifdef SLC_NAMES
|
||||||
|
char *slc_names[] = {
|
||||||
|
SLC_NAMELIST};
|
||||||
|
#else
|
||||||
|
extern char *slc_names[];
|
||||||
|
#define SLC_NAMES SLC_NAMELIST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
|
||||||
|
#define SLC_NAME(x) slc_names[x]
|
||||||
|
|
||||||
|
#define SLC_NOSUPPORT 0
|
||||||
|
#define SLC_CANTCHANGE 1
|
||||||
|
#define SLC_VARIABLE 2
|
||||||
|
#define SLC_DEFAULT 3
|
||||||
|
#define SLC_LEVELBITS 0x03
|
||||||
|
|
||||||
|
#define SLC_FUNC 0
|
||||||
|
#define SLC_FLAGS 1
|
||||||
|
#define SLC_VALUE 2
|
||||||
|
|
||||||
|
#define SLC_ACK 0x80
|
||||||
|
#define SLC_FLUSHIN 0x40
|
||||||
|
#define SLC_FLUSHOUT 0x20
|
||||||
|
|
||||||
|
#define OLD_ENV_VAR 1
|
||||||
|
#define OLD_ENV_VALUE 0
|
||||||
|
#define NEW_ENV_VAR 0
|
||||||
|
#define NEW_ENV_VALUE 1
|
||||||
|
#define ENV_ESC 2
|
||||||
|
#define ENV_USERVAR 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AUTHENTICATION suboptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Who is authenticating who ...
|
||||||
|
*/
|
||||||
|
#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
|
||||||
|
#define AUTH_WHO_SERVER 1 /* Server authenticating client */
|
||||||
|
#define AUTH_WHO_MASK 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* amount of authentication done
|
||||||
|
*/
|
||||||
|
#define AUTH_HOW_ONE_WAY 0
|
||||||
|
#define AUTH_HOW_MUTUAL 2
|
||||||
|
#define AUTH_HOW_MASK 2
|
||||||
|
|
||||||
|
#define AUTHTYPE_NULL 0
|
||||||
|
#define AUTHTYPE_KERBEROS_V4 1
|
||||||
|
#define AUTHTYPE_KERBEROS_V5 2
|
||||||
|
#define AUTHTYPE_SPX 3
|
||||||
|
#define AUTHTYPE_MINK 4
|
||||||
|
#define AUTHTYPE_CNT 5
|
||||||
|
|
||||||
|
#define AUTHTYPE_TEST 99
|
||||||
|
|
||||||
|
#ifdef AUTH_NAMES
|
||||||
|
char *authtype_names[] = {
|
||||||
|
"NULL",
|
||||||
|
"KERBEROS_V4",
|
||||||
|
"KERBEROS_V5",
|
||||||
|
"SPX",
|
||||||
|
"MINK",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *authtype_names[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
|
||||||
|
#define AUTHTYPE_NAME(x) authtype_names[x]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ENCRYPTion suboptions
|
||||||
|
*/
|
||||||
|
#define ENCRYPT_IS 0 /* I pick encryption type ... */
|
||||||
|
#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
|
||||||
|
#define ENCRYPT_REPLY 2 /* Initial setup response */
|
||||||
|
#define ENCRYPT_START 3 /* Am starting to send encrypted */
|
||||||
|
#define ENCRYPT_END 4 /* Am ending encrypted */
|
||||||
|
#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
|
||||||
|
#define ENCRYPT_REQEND 6 /* Request you send encrypting */
|
||||||
|
#define ENCRYPT_ENC_KEYID 7
|
||||||
|
#define ENCRYPT_DEC_KEYID 8
|
||||||
|
#define ENCRYPT_CNT 9
|
||||||
|
|
||||||
|
#define ENCTYPE_ANY 0
|
||||||
|
#define ENCTYPE_DES_CFB64 1
|
||||||
|
#define ENCTYPE_DES_OFB64 2
|
||||||
|
#define ENCTYPE_CNT 3
|
||||||
|
|
||||||
|
#ifdef ENCRYPT_NAMES
|
||||||
|
char *encrypt_names[] = {
|
||||||
|
"IS",
|
||||||
|
"SUPPORT",
|
||||||
|
"REPLY",
|
||||||
|
"START",
|
||||||
|
"END",
|
||||||
|
"REQUEST-START",
|
||||||
|
"REQUEST-END",
|
||||||
|
"ENC-KEYID",
|
||||||
|
"DEC-KEYID",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
char *enctype_names[] = {
|
||||||
|
"ANY",
|
||||||
|
"DES_CFB64",
|
||||||
|
"DES_OFB64",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *encrypt_names[];
|
||||||
|
extern char *enctype_names[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
|
||||||
|
#define ENCRYPT_NAME(x) encrypt_names[x]
|
||||||
|
|
||||||
|
#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
|
||||||
|
#define ENCTYPE_NAME(x) enctype_names[x]
|
||||||
|
|
||||||
|
/*
|
||||||
|
user define
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#define TELNET_PORT 223
|
||||||
|
#define RX_BUFFER_SIZE 1024
|
||||||
|
#define CMD_SIZE 1024
|
||||||
|
#define CMD_HISTERY_NUMBER 5
|
||||||
|
#define TEL_PROMPT "admin@telnet:~$ "
|
||||||
|
#define PASSWD "admin"
|
||||||
|
extern void printp(char *format, ...);
|
||||||
|
#define debug_print(fmt, ...) printp(fmt, ##__VA_ARGS__)
|
||||||
|
// #define debug_print(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
// #define debug_print(fmt, ...)
|
||||||
|
typedef struct telnet_t
|
||||||
|
{
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
int sock_server;
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
int sock_client;
|
||||||
|
unsigned char rec_buff[RX_BUFFER_SIZE];
|
||||||
|
int rec_len;
|
||||||
|
unsigned char cmd_buff[CMD_SIZE];
|
||||||
|
unsigned char history_pos;
|
||||||
|
unsigned char history_total;
|
||||||
|
unsigned char cmd_history[CMD_HISTERY_NUMBER][CMD_SIZE];
|
||||||
|
int cmd_pos;
|
||||||
|
unsigned short win_width;
|
||||||
|
unsigned short win_height;
|
||||||
|
unsigned char cilent_type_name[10];
|
||||||
|
char cilent_type;
|
||||||
|
char *passwd;
|
||||||
|
char passwd_pos;
|
||||||
|
char *tel_prompt;
|
||||||
|
char init : 1;
|
||||||
|
char login_in : 1;
|
||||||
|
char tel_login_show : 1;
|
||||||
|
char input_mode : 2;
|
||||||
|
char table_mode : 2;
|
||||||
|
} telnet_t;
|
||||||
|
|
||||||
|
#endif /* !_TELNET_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,92 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018,2020 Thomas E. Dickey *
|
||||||
|
* Copyright 2006-2012,2017 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Author: Thomas E. Dickey 2006 *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* $Id: nc_tparm.h,v 1.11 2020/05/27 23:33:31 tom Exp $ */
|
||||||
|
|
||||||
|
#ifndef NC_TPARM_included
|
||||||
|
#define NC_TPARM_included 1
|
||||||
|
|
||||||
|
#include <ncurses_cfg.h>
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cast parameters past the formatting-string for tparm() to match the
|
||||||
|
* assumption of the varargs code.
|
||||||
|
*/
|
||||||
|
#ifndef TPARM_ARG
|
||||||
|
#ifdef NCURSES_TPARM_ARG
|
||||||
|
#define TPARM_ARG NCURSES_TPARM_ARG
|
||||||
|
#else
|
||||||
|
#define TPARM_ARG long
|
||||||
|
#endif
|
||||||
|
#endif /* TPARAM_ARG */
|
||||||
|
|
||||||
|
#define TPARM_N(n) (TPARM_ARG)(n)
|
||||||
|
|
||||||
|
#define TPARM_9(a,b,c,d,e,f,g,h,i,j) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h),TPARM_N(i),TPARM_N(j))
|
||||||
|
|
||||||
|
#if NCURSES_TPARM_VARARGS
|
||||||
|
#define TPARM_8(a,b,c,d,e,f,g,h,i) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h),TPARM_N(i))
|
||||||
|
#define TPARM_7(a,b,c,d,e,f,g,h) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h))
|
||||||
|
#define TPARM_6(a,b,c,d,e,f,g) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g))
|
||||||
|
#define TPARM_5(a,b,c,d,e,f) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f))
|
||||||
|
#define TPARM_4(a,b,c,d,e) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e))
|
||||||
|
#define TPARM_3(a,b,c,d) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d))
|
||||||
|
#define TPARM_2(a,b,c) tparm(a,TPARM_N(b),TPARM_N(c))
|
||||||
|
#define TPARM_1(a,b) tparm(a,TPARM_N(b))
|
||||||
|
#define TPARM_0(a) tparm(a)
|
||||||
|
#else
|
||||||
|
#define TPARM_8(a,b,c,d,e,f,g,h,i) TPARM_9(a,b,c,d,e,f,g,h,i,0)
|
||||||
|
#define TPARM_7(a,b,c,d,e,f,g,h) TPARM_8(a,b,c,d,e,f,g,h,0)
|
||||||
|
#define TPARM_6(a,b,c,d,e,f,g) TPARM_7(a,b,c,d,e,f,g,0)
|
||||||
|
#define TPARM_5(a,b,c,d,e,f) TPARM_6(a,b,c,d,e,f,0)
|
||||||
|
#define TPARM_4(a,b,c,d,e) TPARM_5(a,b,c,d,e,0)
|
||||||
|
#define TPARM_3(a,b,c,d) TPARM_4(a,b,c,d,0)
|
||||||
|
#define TPARM_2(a,b,c) TPARM_3(a,b,c,0)
|
||||||
|
#define TPARM_1(a,b) TPARM_2(a,b,0)
|
||||||
|
#define TPARM_0(a) TPARM_1(a,0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
#define TIPARM_1(s,a) _nc_tiparm(1,s,a)
|
||||||
|
#define TIPARM_2(s,a,b) _nc_tiparm(2,s,a,b)
|
||||||
|
#define TIPARM_3(s,a,b,c) _nc_tiparm(3,s,a,b,c)
|
||||||
|
#define TIPARM_4(s,a,b,c,d) _nc_tiparm(4,s,a,b,c,d)
|
||||||
|
#define TIPARM_5(s,a,b,c,d,e) _nc_tiparm(5,s,a,b,c,d,e)
|
||||||
|
#define TIPARM_6(s,a,b,c,d,e,f) _nc_tiparm(6,s,a,b,c,d,e,f)
|
||||||
|
#define TIPARM_7(s,a,b,c,d,e,f,g) _nc_tiparm(7,s,a,b,c,d,e,f,g)
|
||||||
|
#define TIPARM_8(s,a,b,c,d,e,f,g,h) _nc_tiparm(8,s,a,b,c,d,e,f,g,h)
|
||||||
|
#define TIPARM_9(s,a,b,c,d,e,f,g,h,i) _nc_tiparm(9,s,a,b,c,d,e,f,g,h,i)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NC_TPARM_included */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018,2020 Thomas E. Dickey *
|
||||||
|
* Copyright 2009,2014 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
/* $Id: ncurses_dll.h.in,v 1.17 2020/09/05 17:58:47 juergen Exp $ */
|
||||||
|
|
||||||
|
#ifndef NCURSES_DLL_H_incl
|
||||||
|
#define NCURSES_DLL_H_incl 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MinGW gcc (unlike MSYS2 and Cygwin) should define _WIN32 and possibly _WIN64.
|
||||||
|
*/
|
||||||
|
#if defined(__MINGW64__)
|
||||||
|
|
||||||
|
#ifndef _WIN64
|
||||||
|
#define _WIN64 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__MINGW32__)
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#define _WIN32 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 2014-08-02 workaround for broken MinGW compiler.
|
||||||
|
* Oddly, only TRACE is mapped to trace - the other -D's are okay.
|
||||||
|
* suggest TDM as an alternative.
|
||||||
|
*/
|
||||||
|
#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8)
|
||||||
|
|
||||||
|
#ifdef trace
|
||||||
|
#undef trace
|
||||||
|
#define TRACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* broken compiler */
|
||||||
|
|
||||||
|
#endif /* MingW */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For reentrant code, we map the various global variables into SCREEN by
|
||||||
|
* using functions to access them.
|
||||||
|
*/
|
||||||
|
#define NCURSES_PUBLIC_VAR(name) _nc_##name
|
||||||
|
|
||||||
|
#if defined(BUILDING_NCURSES)
|
||||||
|
# define NCURSES_IMPEXP NCURSES_EXPORT_GENERAL_EXPORT
|
||||||
|
#else
|
||||||
|
# define NCURSES_IMPEXP NCURSES_EXPORT_GENERAL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NCURSES_WRAPPED_VAR(type,name) extern NCURSES_IMPEXP type NCURSES_PUBLIC_VAR(name)(void)
|
||||||
|
|
||||||
|
#define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API
|
||||||
|
#define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These symbols hide dllimport/dllexport, for compilers which care about it.
|
||||||
|
*/
|
||||||
|
#if defined(__CYGWIN__) || (defined(_WIN32) || defined(_WIN64))
|
||||||
|
# if defined(NCURSES_STATIC) /* "static" here only implies "not-a-DLL" */
|
||||||
|
# define NCURSES_EXPORT_GENERAL_IMPORT
|
||||||
|
# define NCURSES_EXPORT_GENERAL_EXPORT
|
||||||
|
# else
|
||||||
|
# define NCURSES_EXPORT_GENERAL_IMPORT __declspec(dllimport)
|
||||||
|
# define NCURSES_EXPORT_GENERAL_EXPORT __declspec(dllexport)
|
||||||
|
# endif
|
||||||
|
# define NCURSES_API __cdecl
|
||||||
|
#else
|
||||||
|
# define NCURSES_EXPORT_GENERAL_IMPORT
|
||||||
|
# define NCURSES_EXPORT_GENERAL_EXPORT
|
||||||
|
# define NCURSES_API /* FIXME: __attribute__ ((cdecl)) is only available on x86 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NCURSES_DLL_H_incl */
|
|
@ -0,0 +1,874 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018-2020,2021 Thomas E. Dickey *
|
||||||
|
* Copyright 1998-2013,2017 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 */
|
||||||
|
/* and: Eric S. Raymond <esr@snark.thyrsus.com> */
|
||||||
|
/* and: Thomas E. Dickey 1995-on */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
/* $Id: MKterm.h.awk.in,v 1.82 2021/09/24 17:02:46 tom Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** term.h -- Definition of struct term
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NCURSES_TERM_H_incl
|
||||||
|
#define NCURSES_TERM_H_incl 1
|
||||||
|
|
||||||
|
#undef NCURSES_VERSION
|
||||||
|
#define NCURSES_VERSION "6.4"
|
||||||
|
|
||||||
|
#include <ncurses_dll.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make this file self-contained by providing defaults for the HAVE_TERMIO[S]_H
|
||||||
|
* definition (based on the system for which this was configured).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NCURSES_H
|
||||||
|
|
||||||
|
typedef struct screen SCREEN;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#undef NCURSES_SP_FUNCS
|
||||||
|
#define NCURSES_SP_FUNCS 20221231
|
||||||
|
#undef NCURSES_SP_NAME
|
||||||
|
#define NCURSES_SP_NAME(name) name##_sp
|
||||||
|
|
||||||
|
/* Define the sp-funcs helper function */
|
||||||
|
#undef NCURSES_SP_OUTC
|
||||||
|
#define NCURSES_SP_OUTC NCURSES_SP_NAME(NCURSES_OUTC)
|
||||||
|
typedef int (*NCURSES_SP_OUTC)(SCREEN*, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NCURSES_H */
|
||||||
|
|
||||||
|
#undef NCURSES_CONST
|
||||||
|
#define NCURSES_CONST const
|
||||||
|
|
||||||
|
#undef NCURSES_SBOOL
|
||||||
|
#define NCURSES_SBOOL char
|
||||||
|
|
||||||
|
#undef NCURSES_USE_DATABASE
|
||||||
|
#define NCURSES_USE_DATABASE 1
|
||||||
|
|
||||||
|
#undef NCURSES_USE_TERMCAP
|
||||||
|
#define NCURSES_USE_TERMCAP 0
|
||||||
|
|
||||||
|
#undef NCURSES_XNAMES
|
||||||
|
#define NCURSES_XNAMES 1
|
||||||
|
|
||||||
|
/* We will use these symbols to hide differences between
|
||||||
|
* termios/termio/sgttyb interfaces.
|
||||||
|
*/
|
||||||
|
#undef TTY
|
||||||
|
#undef SET_TTY
|
||||||
|
#undef GET_TTY
|
||||||
|
|
||||||
|
/* Assume POSIX termio if we have the header and function */
|
||||||
|
/* #if HAVE_TERMIOS_H && HAVE_TCGETATTR */
|
||||||
|
#if 1 && 1
|
||||||
|
|
||||||
|
#undef TERMIOS
|
||||||
|
#define TERMIOS 1
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#define TTY struct termios
|
||||||
|
|
||||||
|
#else /* !HAVE_TERMIOS_H */
|
||||||
|
|
||||||
|
/* #if HAVE_TERMIO_H */
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
#undef TERMIOS
|
||||||
|
#define TERMIOS 1
|
||||||
|
|
||||||
|
#include <termio.h>
|
||||||
|
#define TTY struct termio
|
||||||
|
|
||||||
|
#else /* !HAVE_TERMIO_H */
|
||||||
|
|
||||||
|
#if (defined(_WIN32) || defined(_WIN64))
|
||||||
|
#if 0
|
||||||
|
#include <win32_curses.h>
|
||||||
|
#define TTY struct winconmode
|
||||||
|
#else
|
||||||
|
#include <ncurses_mingw.h>
|
||||||
|
#define TTY struct termios
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#undef TERMIOS
|
||||||
|
#include <sgtty.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#define TTY struct sgttyb
|
||||||
|
#endif /* MINGW32 */
|
||||||
|
#endif /* HAVE_TERMIO_H */
|
||||||
|
|
||||||
|
#endif /* HAVE_TERMIOS_H */
|
||||||
|
|
||||||
|
#ifdef TERMIOS
|
||||||
|
#define GET_TTY(fd, buf) tcgetattr(fd, buf)
|
||||||
|
#define SET_TTY(fd, buf) tcsetattr(fd, TCSADRAIN, buf)
|
||||||
|
#elif 0 && (defined(_WIN32) || defined(_WIN64))
|
||||||
|
#define GET_TTY(fd, buf) _nc_console_getmode(_nc_console_fd2handle(fd),buf)
|
||||||
|
#define SET_TTY(fd, buf) _nc_console_setmode(_nc_console_fd2handle(fd),buf)
|
||||||
|
#else
|
||||||
|
#define GET_TTY(fd, buf) gtty(fd, buf)
|
||||||
|
#define SET_TTY(fd, buf) stty(fd, buf)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GCC_NORETURN
|
||||||
|
#define GCC_NORETURN /* nothing */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NAMESIZE 256
|
||||||
|
|
||||||
|
/* The cast works because TERMTYPE is the first data in TERMINAL */
|
||||||
|
#define CUR ((TERMTYPE *)(cur_term))->
|
||||||
|
|
||||||
|
#define auto_left_margin CUR Booleans[0]
|
||||||
|
#define auto_right_margin CUR Booleans[1]
|
||||||
|
#define no_esc_ctlc CUR Booleans[2]
|
||||||
|
#define ceol_standout_glitch CUR Booleans[3]
|
||||||
|
#define eat_newline_glitch CUR Booleans[4]
|
||||||
|
#define erase_overstrike CUR Booleans[5]
|
||||||
|
#define generic_type CUR Booleans[6]
|
||||||
|
#define hard_copy CUR Booleans[7]
|
||||||
|
#define has_meta_key CUR Booleans[8]
|
||||||
|
#define has_status_line CUR Booleans[9]
|
||||||
|
#define insert_null_glitch CUR Booleans[10]
|
||||||
|
#define memory_above CUR Booleans[11]
|
||||||
|
#define memory_below CUR Booleans[12]
|
||||||
|
#define move_insert_mode CUR Booleans[13]
|
||||||
|
#define move_standout_mode CUR Booleans[14]
|
||||||
|
#define over_strike CUR Booleans[15]
|
||||||
|
#define status_line_esc_ok CUR Booleans[16]
|
||||||
|
#define dest_tabs_magic_smso CUR Booleans[17]
|
||||||
|
#define tilde_glitch CUR Booleans[18]
|
||||||
|
#define transparent_underline CUR Booleans[19]
|
||||||
|
#define xon_xoff CUR Booleans[20]
|
||||||
|
#define needs_xon_xoff CUR Booleans[21]
|
||||||
|
#define prtr_silent CUR Booleans[22]
|
||||||
|
#define hard_cursor CUR Booleans[23]
|
||||||
|
#define non_rev_rmcup CUR Booleans[24]
|
||||||
|
#define no_pad_char CUR Booleans[25]
|
||||||
|
#define non_dest_scroll_region CUR Booleans[26]
|
||||||
|
#define can_change CUR Booleans[27]
|
||||||
|
#define back_color_erase CUR Booleans[28]
|
||||||
|
#define hue_lightness_saturation CUR Booleans[29]
|
||||||
|
#define col_addr_glitch CUR Booleans[30]
|
||||||
|
#define cr_cancels_micro_mode CUR Booleans[31]
|
||||||
|
#define has_print_wheel CUR Booleans[32]
|
||||||
|
#define row_addr_glitch CUR Booleans[33]
|
||||||
|
#define semi_auto_right_margin CUR Booleans[34]
|
||||||
|
#define cpi_changes_res CUR Booleans[35]
|
||||||
|
#define lpi_changes_res CUR Booleans[36]
|
||||||
|
#define columns CUR Numbers[0]
|
||||||
|
#define init_tabs CUR Numbers[1]
|
||||||
|
#define lines CUR Numbers[2]
|
||||||
|
#define lines_of_memory CUR Numbers[3]
|
||||||
|
#define magic_cookie_glitch CUR Numbers[4]
|
||||||
|
#define padding_baud_rate CUR Numbers[5]
|
||||||
|
#define virtual_terminal CUR Numbers[6]
|
||||||
|
#define width_status_line CUR Numbers[7]
|
||||||
|
#define num_labels CUR Numbers[8]
|
||||||
|
#define label_height CUR Numbers[9]
|
||||||
|
#define label_width CUR Numbers[10]
|
||||||
|
#define max_attributes CUR Numbers[11]
|
||||||
|
#define maximum_windows CUR Numbers[12]
|
||||||
|
#define max_colors CUR Numbers[13]
|
||||||
|
#define max_pairs CUR Numbers[14]
|
||||||
|
#define no_color_video CUR Numbers[15]
|
||||||
|
#define buffer_capacity CUR Numbers[16]
|
||||||
|
#define dot_vert_spacing CUR Numbers[17]
|
||||||
|
#define dot_horz_spacing CUR Numbers[18]
|
||||||
|
#define max_micro_address CUR Numbers[19]
|
||||||
|
#define max_micro_jump CUR Numbers[20]
|
||||||
|
#define micro_col_size CUR Numbers[21]
|
||||||
|
#define micro_line_size CUR Numbers[22]
|
||||||
|
#define number_of_pins CUR Numbers[23]
|
||||||
|
#define output_res_char CUR Numbers[24]
|
||||||
|
#define output_res_line CUR Numbers[25]
|
||||||
|
#define output_res_horz_inch CUR Numbers[26]
|
||||||
|
#define output_res_vert_inch CUR Numbers[27]
|
||||||
|
#define print_rate CUR Numbers[28]
|
||||||
|
#define wide_char_size CUR Numbers[29]
|
||||||
|
#define buttons CUR Numbers[30]
|
||||||
|
#define bit_image_entwining CUR Numbers[31]
|
||||||
|
#define bit_image_type CUR Numbers[32]
|
||||||
|
#define back_tab CUR Strings[0]
|
||||||
|
#define bell CUR Strings[1]
|
||||||
|
#define carriage_return CUR Strings[2]
|
||||||
|
#define change_scroll_region CUR Strings[3]
|
||||||
|
#define clear_all_tabs CUR Strings[4]
|
||||||
|
#define clear_screen CUR Strings[5]
|
||||||
|
#define clr_eol CUR Strings[6]
|
||||||
|
#define clr_eos CUR Strings[7]
|
||||||
|
#define column_address CUR Strings[8]
|
||||||
|
#define command_character CUR Strings[9]
|
||||||
|
#define cursor_address CUR Strings[10]
|
||||||
|
#define cursor_down CUR Strings[11]
|
||||||
|
#define cursor_home CUR Strings[12]
|
||||||
|
#define cursor_invisible CUR Strings[13]
|
||||||
|
#define cursor_left CUR Strings[14]
|
||||||
|
#define cursor_mem_address CUR Strings[15]
|
||||||
|
#define cursor_normal CUR Strings[16]
|
||||||
|
#define cursor_right CUR Strings[17]
|
||||||
|
#define cursor_to_ll CUR Strings[18]
|
||||||
|
#define cursor_up CUR Strings[19]
|
||||||
|
#define cursor_visible CUR Strings[20]
|
||||||
|
#define delete_character CUR Strings[21]
|
||||||
|
#define delete_line CUR Strings[22]
|
||||||
|
#define dis_status_line CUR Strings[23]
|
||||||
|
#define down_half_line CUR Strings[24]
|
||||||
|
#define enter_alt_charset_mode CUR Strings[25]
|
||||||
|
#define enter_blink_mode CUR Strings[26]
|
||||||
|
#define enter_bold_mode CUR Strings[27]
|
||||||
|
#define enter_ca_mode CUR Strings[28]
|
||||||
|
#define enter_delete_mode CUR Strings[29]
|
||||||
|
#define enter_dim_mode CUR Strings[30]
|
||||||
|
#define enter_insert_mode CUR Strings[31]
|
||||||
|
#define enter_secure_mode CUR Strings[32]
|
||||||
|
#define enter_protected_mode CUR Strings[33]
|
||||||
|
#define enter_reverse_mode CUR Strings[34]
|
||||||
|
#define enter_standout_mode CUR Strings[35]
|
||||||
|
#define enter_underline_mode CUR Strings[36]
|
||||||
|
#define erase_chars CUR Strings[37]
|
||||||
|
#define exit_alt_charset_mode CUR Strings[38]
|
||||||
|
#define exit_attribute_mode CUR Strings[39]
|
||||||
|
#define exit_ca_mode CUR Strings[40]
|
||||||
|
#define exit_delete_mode CUR Strings[41]
|
||||||
|
#define exit_insert_mode CUR Strings[42]
|
||||||
|
#define exit_standout_mode CUR Strings[43]
|
||||||
|
#define exit_underline_mode CUR Strings[44]
|
||||||
|
#define flash_screen CUR Strings[45]
|
||||||
|
#define form_feed CUR Strings[46]
|
||||||
|
#define from_status_line CUR Strings[47]
|
||||||
|
#define init_1string CUR Strings[48]
|
||||||
|
#define init_2string CUR Strings[49]
|
||||||
|
#define init_3string CUR Strings[50]
|
||||||
|
#define init_file CUR Strings[51]
|
||||||
|
#define insert_character CUR Strings[52]
|
||||||
|
#define insert_line CUR Strings[53]
|
||||||
|
#define insert_padding CUR Strings[54]
|
||||||
|
#define key_backspace CUR Strings[55]
|
||||||
|
#define key_catab CUR Strings[56]
|
||||||
|
#define key_clear CUR Strings[57]
|
||||||
|
#define key_ctab CUR Strings[58]
|
||||||
|
#define key_dc CUR Strings[59]
|
||||||
|
#define key_dl CUR Strings[60]
|
||||||
|
#define key_down CUR Strings[61]
|
||||||
|
#define key_eic CUR Strings[62]
|
||||||
|
#define key_eol CUR Strings[63]
|
||||||
|
#define key_eos CUR Strings[64]
|
||||||
|
#define key_f0 CUR Strings[65]
|
||||||
|
#define key_f1 CUR Strings[66]
|
||||||
|
#define key_f10 CUR Strings[67]
|
||||||
|
#define key_f2 CUR Strings[68]
|
||||||
|
#define key_f3 CUR Strings[69]
|
||||||
|
#define key_f4 CUR Strings[70]
|
||||||
|
#define key_f5 CUR Strings[71]
|
||||||
|
#define key_f6 CUR Strings[72]
|
||||||
|
#define key_f7 CUR Strings[73]
|
||||||
|
#define key_f8 CUR Strings[74]
|
||||||
|
#define key_f9 CUR Strings[75]
|
||||||
|
#define key_home CUR Strings[76]
|
||||||
|
#define key_ic CUR Strings[77]
|
||||||
|
#define key_il CUR Strings[78]
|
||||||
|
#define key_left CUR Strings[79]
|
||||||
|
#define key_ll CUR Strings[80]
|
||||||
|
#define key_npage CUR Strings[81]
|
||||||
|
#define key_ppage CUR Strings[82]
|
||||||
|
#define key_right CUR Strings[83]
|
||||||
|
#define key_sf CUR Strings[84]
|
||||||
|
#define key_sr CUR Strings[85]
|
||||||
|
#define key_stab CUR Strings[86]
|
||||||
|
#define key_up CUR Strings[87]
|
||||||
|
#define keypad_local CUR Strings[88]
|
||||||
|
#define keypad_xmit CUR Strings[89]
|
||||||
|
#define lab_f0 CUR Strings[90]
|
||||||
|
#define lab_f1 CUR Strings[91]
|
||||||
|
#define lab_f10 CUR Strings[92]
|
||||||
|
#define lab_f2 CUR Strings[93]
|
||||||
|
#define lab_f3 CUR Strings[94]
|
||||||
|
#define lab_f4 CUR Strings[95]
|
||||||
|
#define lab_f5 CUR Strings[96]
|
||||||
|
#define lab_f6 CUR Strings[97]
|
||||||
|
#define lab_f7 CUR Strings[98]
|
||||||
|
#define lab_f8 CUR Strings[99]
|
||||||
|
#define lab_f9 CUR Strings[100]
|
||||||
|
#define meta_off CUR Strings[101]
|
||||||
|
#define meta_on CUR Strings[102]
|
||||||
|
#define newline CUR Strings[103]
|
||||||
|
#define pad_char CUR Strings[104]
|
||||||
|
#define parm_dch CUR Strings[105]
|
||||||
|
#define parm_delete_line CUR Strings[106]
|
||||||
|
#define parm_down_cursor CUR Strings[107]
|
||||||
|
#define parm_ich CUR Strings[108]
|
||||||
|
#define parm_index CUR Strings[109]
|
||||||
|
#define parm_insert_line CUR Strings[110]
|
||||||
|
#define parm_left_cursor CUR Strings[111]
|
||||||
|
#define parm_right_cursor CUR Strings[112]
|
||||||
|
#define parm_rindex CUR Strings[113]
|
||||||
|
#define parm_up_cursor CUR Strings[114]
|
||||||
|
#define pkey_key CUR Strings[115]
|
||||||
|
#define pkey_local CUR Strings[116]
|
||||||
|
#define pkey_xmit CUR Strings[117]
|
||||||
|
#define print_screen CUR Strings[118]
|
||||||
|
#define prtr_off CUR Strings[119]
|
||||||
|
#define prtr_on CUR Strings[120]
|
||||||
|
#define repeat_char CUR Strings[121]
|
||||||
|
#define reset_1string CUR Strings[122]
|
||||||
|
#define reset_2string CUR Strings[123]
|
||||||
|
#define reset_3string CUR Strings[124]
|
||||||
|
#define reset_file CUR Strings[125]
|
||||||
|
#define restore_cursor CUR Strings[126]
|
||||||
|
#define row_address CUR Strings[127]
|
||||||
|
#define save_cursor CUR Strings[128]
|
||||||
|
#define scroll_forward CUR Strings[129]
|
||||||
|
#define scroll_reverse CUR Strings[130]
|
||||||
|
#define set_attributes CUR Strings[131]
|
||||||
|
#define set_tab CUR Strings[132]
|
||||||
|
#define set_window CUR Strings[133]
|
||||||
|
#define tab CUR Strings[134]
|
||||||
|
#define to_status_line CUR Strings[135]
|
||||||
|
#define underline_char CUR Strings[136]
|
||||||
|
#define up_half_line CUR Strings[137]
|
||||||
|
#define init_prog CUR Strings[138]
|
||||||
|
#define key_a1 CUR Strings[139]
|
||||||
|
#define key_a3 CUR Strings[140]
|
||||||
|
#define key_b2 CUR Strings[141]
|
||||||
|
#define key_c1 CUR Strings[142]
|
||||||
|
#define key_c3 CUR Strings[143]
|
||||||
|
#define prtr_non CUR Strings[144]
|
||||||
|
#define char_padding CUR Strings[145]
|
||||||
|
#define acs_chars CUR Strings[146]
|
||||||
|
#define plab_norm CUR Strings[147]
|
||||||
|
#define key_btab CUR Strings[148]
|
||||||
|
#define enter_xon_mode CUR Strings[149]
|
||||||
|
#define exit_xon_mode CUR Strings[150]
|
||||||
|
#define enter_am_mode CUR Strings[151]
|
||||||
|
#define exit_am_mode CUR Strings[152]
|
||||||
|
#define xon_character CUR Strings[153]
|
||||||
|
#define xoff_character CUR Strings[154]
|
||||||
|
#define ena_acs CUR Strings[155]
|
||||||
|
#define label_on CUR Strings[156]
|
||||||
|
#define label_off CUR Strings[157]
|
||||||
|
#define key_beg CUR Strings[158]
|
||||||
|
#define key_cancel CUR Strings[159]
|
||||||
|
#define key_close CUR Strings[160]
|
||||||
|
#define key_command CUR Strings[161]
|
||||||
|
#define key_copy CUR Strings[162]
|
||||||
|
#define key_create CUR Strings[163]
|
||||||
|
#define key_end CUR Strings[164]
|
||||||
|
#define key_enter CUR Strings[165]
|
||||||
|
#define key_exit CUR Strings[166]
|
||||||
|
#define key_find CUR Strings[167]
|
||||||
|
#define key_help CUR Strings[168]
|
||||||
|
#define key_mark CUR Strings[169]
|
||||||
|
#define key_message CUR Strings[170]
|
||||||
|
#define key_move CUR Strings[171]
|
||||||
|
#define key_next CUR Strings[172]
|
||||||
|
#define key_open CUR Strings[173]
|
||||||
|
#define key_options CUR Strings[174]
|
||||||
|
#define key_previous CUR Strings[175]
|
||||||
|
#define key_print CUR Strings[176]
|
||||||
|
#define key_redo CUR Strings[177]
|
||||||
|
#define key_reference CUR Strings[178]
|
||||||
|
#define key_refresh CUR Strings[179]
|
||||||
|
#define key_replace CUR Strings[180]
|
||||||
|
#define key_restart CUR Strings[181]
|
||||||
|
#define key_resume CUR Strings[182]
|
||||||
|
#define key_save CUR Strings[183]
|
||||||
|
#define key_suspend CUR Strings[184]
|
||||||
|
#define key_undo CUR Strings[185]
|
||||||
|
#define key_sbeg CUR Strings[186]
|
||||||
|
#define key_scancel CUR Strings[187]
|
||||||
|
#define key_scommand CUR Strings[188]
|
||||||
|
#define key_scopy CUR Strings[189]
|
||||||
|
#define key_screate CUR Strings[190]
|
||||||
|
#define key_sdc CUR Strings[191]
|
||||||
|
#define key_sdl CUR Strings[192]
|
||||||
|
#define key_select CUR Strings[193]
|
||||||
|
#define key_send CUR Strings[194]
|
||||||
|
#define key_seol CUR Strings[195]
|
||||||
|
#define key_sexit CUR Strings[196]
|
||||||
|
#define key_sfind CUR Strings[197]
|
||||||
|
#define key_shelp CUR Strings[198]
|
||||||
|
#define key_shome CUR Strings[199]
|
||||||
|
#define key_sic CUR Strings[200]
|
||||||
|
#define key_sleft CUR Strings[201]
|
||||||
|
#define key_smessage CUR Strings[202]
|
||||||
|
#define key_smove CUR Strings[203]
|
||||||
|
#define key_snext CUR Strings[204]
|
||||||
|
#define key_soptions CUR Strings[205]
|
||||||
|
#define key_sprevious CUR Strings[206]
|
||||||
|
#define key_sprint CUR Strings[207]
|
||||||
|
#define key_sredo CUR Strings[208]
|
||||||
|
#define key_sreplace CUR Strings[209]
|
||||||
|
#define key_sright CUR Strings[210]
|
||||||
|
#define key_srsume CUR Strings[211]
|
||||||
|
#define key_ssave CUR Strings[212]
|
||||||
|
#define key_ssuspend CUR Strings[213]
|
||||||
|
#define key_sundo CUR Strings[214]
|
||||||
|
#define req_for_input CUR Strings[215]
|
||||||
|
#define key_f11 CUR Strings[216]
|
||||||
|
#define key_f12 CUR Strings[217]
|
||||||
|
#define key_f13 CUR Strings[218]
|
||||||
|
#define key_f14 CUR Strings[219]
|
||||||
|
#define key_f15 CUR Strings[220]
|
||||||
|
#define key_f16 CUR Strings[221]
|
||||||
|
#define key_f17 CUR Strings[222]
|
||||||
|
#define key_f18 CUR Strings[223]
|
||||||
|
#define key_f19 CUR Strings[224]
|
||||||
|
#define key_f20 CUR Strings[225]
|
||||||
|
#define key_f21 CUR Strings[226]
|
||||||
|
#define key_f22 CUR Strings[227]
|
||||||
|
#define key_f23 CUR Strings[228]
|
||||||
|
#define key_f24 CUR Strings[229]
|
||||||
|
#define key_f25 CUR Strings[230]
|
||||||
|
#define key_f26 CUR Strings[231]
|
||||||
|
#define key_f27 CUR Strings[232]
|
||||||
|
#define key_f28 CUR Strings[233]
|
||||||
|
#define key_f29 CUR Strings[234]
|
||||||
|
#define key_f30 CUR Strings[235]
|
||||||
|
#define key_f31 CUR Strings[236]
|
||||||
|
#define key_f32 CUR Strings[237]
|
||||||
|
#define key_f33 CUR Strings[238]
|
||||||
|
#define key_f34 CUR Strings[239]
|
||||||
|
#define key_f35 CUR Strings[240]
|
||||||
|
#define key_f36 CUR Strings[241]
|
||||||
|
#define key_f37 CUR Strings[242]
|
||||||
|
#define key_f38 CUR Strings[243]
|
||||||
|
#define key_f39 CUR Strings[244]
|
||||||
|
#define key_f40 CUR Strings[245]
|
||||||
|
#define key_f41 CUR Strings[246]
|
||||||
|
#define key_f42 CUR Strings[247]
|
||||||
|
#define key_f43 CUR Strings[248]
|
||||||
|
#define key_f44 CUR Strings[249]
|
||||||
|
#define key_f45 CUR Strings[250]
|
||||||
|
#define key_f46 CUR Strings[251]
|
||||||
|
#define key_f47 CUR Strings[252]
|
||||||
|
#define key_f48 CUR Strings[253]
|
||||||
|
#define key_f49 CUR Strings[254]
|
||||||
|
#define key_f50 CUR Strings[255]
|
||||||
|
#define key_f51 CUR Strings[256]
|
||||||
|
#define key_f52 CUR Strings[257]
|
||||||
|
#define key_f53 CUR Strings[258]
|
||||||
|
#define key_f54 CUR Strings[259]
|
||||||
|
#define key_f55 CUR Strings[260]
|
||||||
|
#define key_f56 CUR Strings[261]
|
||||||
|
#define key_f57 CUR Strings[262]
|
||||||
|
#define key_f58 CUR Strings[263]
|
||||||
|
#define key_f59 CUR Strings[264]
|
||||||
|
#define key_f60 CUR Strings[265]
|
||||||
|
#define key_f61 CUR Strings[266]
|
||||||
|
#define key_f62 CUR Strings[267]
|
||||||
|
#define key_f63 CUR Strings[268]
|
||||||
|
#define clr_bol CUR Strings[269]
|
||||||
|
#define clear_margins CUR Strings[270]
|
||||||
|
#define set_left_margin CUR Strings[271]
|
||||||
|
#define set_right_margin CUR Strings[272]
|
||||||
|
#define label_format CUR Strings[273]
|
||||||
|
#define set_clock CUR Strings[274]
|
||||||
|
#define display_clock CUR Strings[275]
|
||||||
|
#define remove_clock CUR Strings[276]
|
||||||
|
#define create_window CUR Strings[277]
|
||||||
|
#define goto_window CUR Strings[278]
|
||||||
|
#define hangup CUR Strings[279]
|
||||||
|
#define dial_phone CUR Strings[280]
|
||||||
|
#define quick_dial CUR Strings[281]
|
||||||
|
#define tone CUR Strings[282]
|
||||||
|
#define pulse CUR Strings[283]
|
||||||
|
#define flash_hook CUR Strings[284]
|
||||||
|
#define fixed_pause CUR Strings[285]
|
||||||
|
#define wait_tone CUR Strings[286]
|
||||||
|
#define user0 CUR Strings[287]
|
||||||
|
#define user1 CUR Strings[288]
|
||||||
|
#define user2 CUR Strings[289]
|
||||||
|
#define user3 CUR Strings[290]
|
||||||
|
#define user4 CUR Strings[291]
|
||||||
|
#define user5 CUR Strings[292]
|
||||||
|
#define user6 CUR Strings[293]
|
||||||
|
#define user7 CUR Strings[294]
|
||||||
|
#define user8 CUR Strings[295]
|
||||||
|
#define user9 CUR Strings[296]
|
||||||
|
#define orig_pair CUR Strings[297]
|
||||||
|
#define orig_colors CUR Strings[298]
|
||||||
|
#define initialize_color CUR Strings[299]
|
||||||
|
#define initialize_pair CUR Strings[300]
|
||||||
|
#define set_color_pair CUR Strings[301]
|
||||||
|
#define set_foreground CUR Strings[302]
|
||||||
|
#define set_background CUR Strings[303]
|
||||||
|
#define change_char_pitch CUR Strings[304]
|
||||||
|
#define change_line_pitch CUR Strings[305]
|
||||||
|
#define change_res_horz CUR Strings[306]
|
||||||
|
#define change_res_vert CUR Strings[307]
|
||||||
|
#define define_char CUR Strings[308]
|
||||||
|
#define enter_doublewide_mode CUR Strings[309]
|
||||||
|
#define enter_draft_quality CUR Strings[310]
|
||||||
|
#define enter_italics_mode CUR Strings[311]
|
||||||
|
#define enter_leftward_mode CUR Strings[312]
|
||||||
|
#define enter_micro_mode CUR Strings[313]
|
||||||
|
#define enter_near_letter_quality CUR Strings[314]
|
||||||
|
#define enter_normal_quality CUR Strings[315]
|
||||||
|
#define enter_shadow_mode CUR Strings[316]
|
||||||
|
#define enter_subscript_mode CUR Strings[317]
|
||||||
|
#define enter_superscript_mode CUR Strings[318]
|
||||||
|
#define enter_upward_mode CUR Strings[319]
|
||||||
|
#define exit_doublewide_mode CUR Strings[320]
|
||||||
|
#define exit_italics_mode CUR Strings[321]
|
||||||
|
#define exit_leftward_mode CUR Strings[322]
|
||||||
|
#define exit_micro_mode CUR Strings[323]
|
||||||
|
#define exit_shadow_mode CUR Strings[324]
|
||||||
|
#define exit_subscript_mode CUR Strings[325]
|
||||||
|
#define exit_superscript_mode CUR Strings[326]
|
||||||
|
#define exit_upward_mode CUR Strings[327]
|
||||||
|
#define micro_column_address CUR Strings[328]
|
||||||
|
#define micro_down CUR Strings[329]
|
||||||
|
#define micro_left CUR Strings[330]
|
||||||
|
#define micro_right CUR Strings[331]
|
||||||
|
#define micro_row_address CUR Strings[332]
|
||||||
|
#define micro_up CUR Strings[333]
|
||||||
|
#define order_of_pins CUR Strings[334]
|
||||||
|
#define parm_down_micro CUR Strings[335]
|
||||||
|
#define parm_left_micro CUR Strings[336]
|
||||||
|
#define parm_right_micro CUR Strings[337]
|
||||||
|
#define parm_up_micro CUR Strings[338]
|
||||||
|
#define select_char_set CUR Strings[339]
|
||||||
|
#define set_bottom_margin CUR Strings[340]
|
||||||
|
#define set_bottom_margin_parm CUR Strings[341]
|
||||||
|
#define set_left_margin_parm CUR Strings[342]
|
||||||
|
#define set_right_margin_parm CUR Strings[343]
|
||||||
|
#define set_top_margin CUR Strings[344]
|
||||||
|
#define set_top_margin_parm CUR Strings[345]
|
||||||
|
#define start_bit_image CUR Strings[346]
|
||||||
|
#define start_char_set_def CUR Strings[347]
|
||||||
|
#define stop_bit_image CUR Strings[348]
|
||||||
|
#define stop_char_set_def CUR Strings[349]
|
||||||
|
#define subscript_characters CUR Strings[350]
|
||||||
|
#define superscript_characters CUR Strings[351]
|
||||||
|
#define these_cause_cr CUR Strings[352]
|
||||||
|
#define zero_motion CUR Strings[353]
|
||||||
|
#define char_set_names CUR Strings[354]
|
||||||
|
#define key_mouse CUR Strings[355]
|
||||||
|
#define mouse_info CUR Strings[356]
|
||||||
|
#define req_mouse_pos CUR Strings[357]
|
||||||
|
#define get_mouse CUR Strings[358]
|
||||||
|
#define set_a_foreground CUR Strings[359]
|
||||||
|
#define set_a_background CUR Strings[360]
|
||||||
|
#define pkey_plab CUR Strings[361]
|
||||||
|
#define device_type CUR Strings[362]
|
||||||
|
#define code_set_init CUR Strings[363]
|
||||||
|
#define set0_des_seq CUR Strings[364]
|
||||||
|
#define set1_des_seq CUR Strings[365]
|
||||||
|
#define set2_des_seq CUR Strings[366]
|
||||||
|
#define set3_des_seq CUR Strings[367]
|
||||||
|
#define set_lr_margin CUR Strings[368]
|
||||||
|
#define set_tb_margin CUR Strings[369]
|
||||||
|
#define bit_image_repeat CUR Strings[370]
|
||||||
|
#define bit_image_newline CUR Strings[371]
|
||||||
|
#define bit_image_carriage_return CUR Strings[372]
|
||||||
|
#define color_names CUR Strings[373]
|
||||||
|
#define define_bit_image_region CUR Strings[374]
|
||||||
|
#define end_bit_image_region CUR Strings[375]
|
||||||
|
#define set_color_band CUR Strings[376]
|
||||||
|
#define set_page_length CUR Strings[377]
|
||||||
|
#define display_pc_char CUR Strings[378]
|
||||||
|
#define enter_pc_charset_mode CUR Strings[379]
|
||||||
|
#define exit_pc_charset_mode CUR Strings[380]
|
||||||
|
#define enter_scancode_mode CUR Strings[381]
|
||||||
|
#define exit_scancode_mode CUR Strings[382]
|
||||||
|
#define pc_term_options CUR Strings[383]
|
||||||
|
#define scancode_escape CUR Strings[384]
|
||||||
|
#define alt_scancode_esc CUR Strings[385]
|
||||||
|
#define enter_horizontal_hl_mode CUR Strings[386]
|
||||||
|
#define enter_left_hl_mode CUR Strings[387]
|
||||||
|
#define enter_low_hl_mode CUR Strings[388]
|
||||||
|
#define enter_right_hl_mode CUR Strings[389]
|
||||||
|
#define enter_top_hl_mode CUR Strings[390]
|
||||||
|
#define enter_vertical_hl_mode CUR Strings[391]
|
||||||
|
#define set_a_attributes CUR Strings[392]
|
||||||
|
#define set_pglen_inch CUR Strings[393]
|
||||||
|
|
||||||
|
#define BOOLWRITE 37
|
||||||
|
#define NUMWRITE 33
|
||||||
|
#define STRWRITE 394
|
||||||
|
|
||||||
|
/* older synonyms for some capabilities */
|
||||||
|
#define beehive_glitch no_esc_ctlc
|
||||||
|
#define teleray_glitch dest_tabs_magic_smso
|
||||||
|
|
||||||
|
/* HPUX-11 uses this name rather than the standard one */
|
||||||
|
#ifndef micro_char_size
|
||||||
|
#define micro_char_size micro_col_size
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __INTERNAL_CAPS_VISIBLE
|
||||||
|
#define termcap_init2 CUR Strings[394]
|
||||||
|
#define termcap_reset CUR Strings[395]
|
||||||
|
#define magic_cookie_glitch_ul CUR Numbers[33]
|
||||||
|
#define backspaces_with_bs CUR Booleans[37]
|
||||||
|
#define crt_no_scrolling CUR Booleans[38]
|
||||||
|
#define no_correctly_working_cr CUR Booleans[39]
|
||||||
|
#define carriage_return_delay CUR Numbers[34]
|
||||||
|
#define new_line_delay CUR Numbers[35]
|
||||||
|
#define linefeed_if_not_lf CUR Strings[396]
|
||||||
|
#define backspace_if_not_bs CUR Strings[397]
|
||||||
|
#define gnu_has_meta_key CUR Booleans[40]
|
||||||
|
#define linefeed_is_newline CUR Booleans[41]
|
||||||
|
#define backspace_delay CUR Numbers[36]
|
||||||
|
#define horizontal_tab_delay CUR Numbers[37]
|
||||||
|
#define number_of_function_keys CUR Numbers[38]
|
||||||
|
#define other_non_function_keys CUR Strings[398]
|
||||||
|
#define arrow_key_map CUR Strings[399]
|
||||||
|
#define has_hardware_tabs CUR Booleans[42]
|
||||||
|
#define return_does_clr_eol CUR Booleans[43]
|
||||||
|
#define acs_ulcorner CUR Strings[400]
|
||||||
|
#define acs_llcorner CUR Strings[401]
|
||||||
|
#define acs_urcorner CUR Strings[402]
|
||||||
|
#define acs_lrcorner CUR Strings[403]
|
||||||
|
#define acs_ltee CUR Strings[404]
|
||||||
|
#define acs_rtee CUR Strings[405]
|
||||||
|
#define acs_btee CUR Strings[406]
|
||||||
|
#define acs_ttee CUR Strings[407]
|
||||||
|
#define acs_hline CUR Strings[408]
|
||||||
|
#define acs_vline CUR Strings[409]
|
||||||
|
#define acs_plus CUR Strings[410]
|
||||||
|
#define memory_lock CUR Strings[411]
|
||||||
|
#define memory_unlock CUR Strings[412]
|
||||||
|
#define box_chars_1 CUR Strings[413]
|
||||||
|
#endif /* __INTERNAL_CAPS_VISIBLE */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Predefined terminfo array sizes
|
||||||
|
*/
|
||||||
|
#define BOOLCOUNT 44
|
||||||
|
#define NUMCOUNT 39
|
||||||
|
#define STRCOUNT 414
|
||||||
|
|
||||||
|
/* used by code for comparing entries */
|
||||||
|
#define acs_chars_index 146
|
||||||
|
|
||||||
|
typedef struct termtype { /* in-core form of terminfo data */
|
||||||
|
char *term_names; /* str_table offset of term names */
|
||||||
|
char *str_table; /* pointer to string table */
|
||||||
|
NCURSES_SBOOL *Booleans; /* array of boolean values */
|
||||||
|
short *Numbers; /* array of integer values */
|
||||||
|
char **Strings; /* array of string offsets */
|
||||||
|
|
||||||
|
#if NCURSES_XNAMES
|
||||||
|
char *ext_str_table; /* pointer to extended string table */
|
||||||
|
char **ext_Names; /* corresponding names */
|
||||||
|
|
||||||
|
unsigned short num_Booleans;/* count total Booleans */
|
||||||
|
unsigned short num_Numbers; /* count total Numbers */
|
||||||
|
unsigned short num_Strings; /* count total Strings */
|
||||||
|
|
||||||
|
unsigned short ext_Booleans;/* count extensions to Booleans */
|
||||||
|
unsigned short ext_Numbers; /* count extensions to Numbers */
|
||||||
|
unsigned short ext_Strings; /* count extensions to Strings */
|
||||||
|
#endif /* NCURSES_XNAMES */
|
||||||
|
|
||||||
|
} TERMTYPE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The only reason these structures are visible is for read-only use.
|
||||||
|
* Programs which modify the data are not, never were, portable across
|
||||||
|
* curses implementations.
|
||||||
|
*
|
||||||
|
* The first field in TERMINAL is used in macros.
|
||||||
|
* The remaining fields are private.
|
||||||
|
*/
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
|
||||||
|
#undef TERMINAL
|
||||||
|
#define TERMINAL struct term
|
||||||
|
TERMINAL;
|
||||||
|
|
||||||
|
#undef TERMTYPE2
|
||||||
|
#define TERMTYPE2 TERMTYPE
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef struct term { /* describe an actual terminal */
|
||||||
|
TERMTYPE type; /* terminal type description */
|
||||||
|
} TERMINAL;
|
||||||
|
|
||||||
|
#endif /* NCURSES_INTERNALS */
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 && !0
|
||||||
|
extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term;
|
||||||
|
#elif 0
|
||||||
|
NCURSES_WRAPPED_VAR(TERMINAL *, cur_term);
|
||||||
|
#define cur_term NCURSES_PUBLIC_VAR(cur_term())
|
||||||
|
#else
|
||||||
|
extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 || 0
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolnames);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolcodes);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolfnames);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numnames);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numcodes);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, numfnames);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strnames);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strcodes);
|
||||||
|
NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strfnames);
|
||||||
|
|
||||||
|
#define boolnames NCURSES_PUBLIC_VAR(boolnames())
|
||||||
|
#define boolcodes NCURSES_PUBLIC_VAR(boolcodes())
|
||||||
|
#define boolfnames NCURSES_PUBLIC_VAR(boolfnames())
|
||||||
|
#define numnames NCURSES_PUBLIC_VAR(numnames())
|
||||||
|
#define numcodes NCURSES_PUBLIC_VAR(numcodes())
|
||||||
|
#define numfnames NCURSES_PUBLIC_VAR(numfnames())
|
||||||
|
#define strnames NCURSES_PUBLIC_VAR(strnames())
|
||||||
|
#define strcodes NCURSES_PUBLIC_VAR(strcodes())
|
||||||
|
#define strfnames NCURSES_PUBLIC_VAR(strfnames())
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolnames[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolcodes[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolfnames[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numnames[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numcodes[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) numfnames[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strnames[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strcodes[];
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strfnames[];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints are used only by the ncurses utilities such as tic.
|
||||||
|
*/
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(int) _nc_set_tty_mode (TTY *buf);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_read_entry2 (const char * const, char * const, TERMTYPE2 *const);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_read_file_entry (const char *const, TERMTYPE2 *);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_read_termtype (TERMTYPE2 *, char *, int);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_first_name (const char *const);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_name_match (const char *const, const char *const, const char *const);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_tiparm(int, const char *, ...);
|
||||||
|
|
||||||
|
#endif /* NCURSES_INTERNALS */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints are used by tack 1.07.
|
||||||
|
*/
|
||||||
|
extern NCURSES_EXPORT(const TERMTYPE *) _nc_fallback (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_read_entry (const char * const, char * const, TERMTYPE *const);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normal entry points
|
||||||
|
*/
|
||||||
|
extern NCURSES_EXPORT(TERMINAL *) set_curterm (TERMINAL *);
|
||||||
|
extern NCURSES_EXPORT(int) del_curterm (TERMINAL *);
|
||||||
|
|
||||||
|
/* miscellaneous entry points */
|
||||||
|
extern NCURSES_EXPORT(int) restartterm (NCURSES_CONST char *, int, int *);
|
||||||
|
extern NCURSES_EXPORT(int) setupterm (const char *,int,int *);
|
||||||
|
|
||||||
|
/* terminfo entry points, also declared in curses.h */
|
||||||
|
#if !defined(__NCURSES_H)
|
||||||
|
extern NCURSES_EXPORT(char *) tigetstr (const char *);
|
||||||
|
extern NCURSES_EXPORT_VAR(char) ttytype[];
|
||||||
|
extern NCURSES_EXPORT(int) putp (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tigetflag (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tigetnum (const char *);
|
||||||
|
|
||||||
|
#if 1 /* NCURSES_TPARM_VARARGS */
|
||||||
|
extern NCURSES_EXPORT(char *) tparm (const char *, ...); /* special */
|
||||||
|
#else
|
||||||
|
extern NCURSES_EXPORT(char *) tparm (const char *, long,long,long,long,long,long,long,long,long); /* special */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */
|
||||||
|
|
||||||
|
#endif /* __NCURSES_H */
|
||||||
|
|
||||||
|
/* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */
|
||||||
|
#if !defined(NCURSES_TERMCAP_H_incl)
|
||||||
|
extern NCURSES_EXPORT(char *) tgetstr (const char *, char **);
|
||||||
|
extern NCURSES_EXPORT(char *) tgoto (const char *, int, int);
|
||||||
|
extern NCURSES_EXPORT(int) tgetent (char *, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tgetflag (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tgetnum (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int));
|
||||||
|
#endif /* NCURSES_TERMCAP_H_incl */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include curses.h before term.h to enable these extensions.
|
||||||
|
*/
|
||||||
|
#if defined(NCURSES_SP_FUNCS) && (NCURSES_SP_FUNCS != 0)
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tigetstr) (SCREEN*, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(putp) (SCREEN*, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetflag) (SCREEN*, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetnum) (SCREEN*, const char *);
|
||||||
|
|
||||||
|
#if 1 /* NCURSES_TPARM_VARARGS */
|
||||||
|
extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, const char *, ...); /* special */
|
||||||
|
#else
|
||||||
|
extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, const char *, long,long,long,long,long,long,long,long,long); /* special */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */
|
||||||
|
extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgetstr) (SCREEN*, const char *, char **);
|
||||||
|
extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgoto) (SCREEN*, const char *, int, int);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetent) (SCREEN*, char *, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetflag) (SCREEN*, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetnum) (SCREEN*, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tputs) (SCREEN*, const char *, int, NCURSES_SP_OUTC);
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(TERMINAL *) NCURSES_SP_NAME(set_curterm) (SCREEN*, TERMINAL *);
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(del_curterm) (SCREEN*, TERMINAL *);
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(int) NCURSES_SP_NAME(restartterm) (SCREEN*, NCURSES_CONST char *, int, int *);
|
||||||
|
#endif /* NCURSES_SP_FUNCS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debugging features.
|
||||||
|
*/
|
||||||
|
extern GCC_NORETURN NCURSES_EXPORT(void) exit_terminfo(int);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NCURSES_TERM_H_incl */
|
|
@ -0,0 +1,239 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018-2021,2022 Thomas E. Dickey *
|
||||||
|
* Copyright 1998-2015,2017 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
||||||
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
||||||
|
* and: Thomas E. Dickey 1998-on *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* $Id: term_entry.h,v 1.63 2022/09/24 15:04:59 tom Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* term_entry.h -- interface to entry-manipulation code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NCURSES_TERM_ENTRY_H_incl
|
||||||
|
#define NCURSES_TERM_ENTRY_H_incl 1
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <term.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros may be used by programs that know about TERMTYPE:
|
||||||
|
*/
|
||||||
|
#if NCURSES_XNAMES
|
||||||
|
#define NUM_BOOLEANS(tp) (tp)->num_Booleans
|
||||||
|
#define NUM_NUMBERS(tp) (tp)->num_Numbers
|
||||||
|
#define NUM_STRINGS(tp) (tp)->num_Strings
|
||||||
|
#define EXT_NAMES(tp,i,limit,index,table) (i >= limit) ? tp->ext_Names[index] : table[i]
|
||||||
|
#else
|
||||||
|
#define NUM_BOOLEANS(tp) BOOLCOUNT
|
||||||
|
#define NUM_NUMBERS(tp) NUMCOUNT
|
||||||
|
#define NUM_STRINGS(tp) STRCOUNT
|
||||||
|
#define EXT_NAMES(tp,i,limit,index,table) table[i]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUM_EXT_NAMES(tp) (unsigned) ((tp)->ext_Booleans + (tp)->ext_Numbers + (tp)->ext_Strings)
|
||||||
|
|
||||||
|
#define for_each_boolean(n,tp) for(n = 0; n < NUM_BOOLEANS(tp); n++)
|
||||||
|
#define for_each_number(n,tp) for(n = 0; n < NUM_NUMBERS(tp); n++)
|
||||||
|
#define for_each_string(n,tp) for(n = 0; n < NUM_STRINGS(tp); n++)
|
||||||
|
|
||||||
|
#if NCURSES_XNAMES
|
||||||
|
#define for_each_ext_boolean(n,tp) for(n = BOOLCOUNT; (int) n < (int) NUM_BOOLEANS(tp); n++)
|
||||||
|
#define for_each_ext_number(n,tp) for(n = NUMCOUNT; (int) n < (int) NUM_NUMBERS(tp); n++)
|
||||||
|
#define for_each_ext_string(n,tp) for(n = STRCOUNT; (int) n < (int) NUM_STRINGS(tp); n++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ExtBoolname(tp,i,names) EXT_NAMES(tp, i, BOOLCOUNT, (i - (tp->num_Booleans - tp->ext_Booleans)), names)
|
||||||
|
#define ExtNumname(tp,i,names) EXT_NAMES(tp, i, NUMCOUNT, (i - (tp->num_Numbers - tp->ext_Numbers)) + tp->ext_Booleans, names)
|
||||||
|
#define ExtStrname(tp,i,names) EXT_NAMES(tp, i, STRCOUNT, (i - (tp->num_Strings - tp->ext_Strings)) + (tp->ext_Numbers + tp->ext_Booleans), names)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining type-definitions and macros are used only internally by the
|
||||||
|
* ncurses utilities.
|
||||||
|
*/
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see db_iterator.c - this enumeration lists the places searched for a
|
||||||
|
* terminal description and defines the order in which they are searched.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
dbdTIC = 0, /* special, used by tic when writing entry */
|
||||||
|
#if NCURSES_USE_DATABASE
|
||||||
|
dbdEnvOnce, /* the $TERMINFO environment variable */
|
||||||
|
dbdHome, /* $HOME/.terminfo */
|
||||||
|
dbdEnvList, /* the $TERMINFO_DIRS environment variable */
|
||||||
|
dbdCfgList, /* the compiled-in TERMINFO_DIRS value */
|
||||||
|
dbdCfgOnce, /* the compiled-in TERMINFO value */
|
||||||
|
#endif
|
||||||
|
#if NCURSES_USE_TERMCAP
|
||||||
|
dbdEnvOnce2, /* the $TERMCAP environment variable */
|
||||||
|
dbdEnvList2, /* the $TERMPATH environment variable */
|
||||||
|
dbdCfgList2, /* the compiled-in TERMPATH */
|
||||||
|
#endif
|
||||||
|
dbdLAST
|
||||||
|
} DBDIRS;
|
||||||
|
|
||||||
|
#define MAX_USES 32
|
||||||
|
#define MAX_CROSSLINKS 16
|
||||||
|
|
||||||
|
typedef struct entry ENTRY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
ENTRY *link;
|
||||||
|
long line;
|
||||||
|
} ENTRY_USES;
|
||||||
|
|
||||||
|
struct entry {
|
||||||
|
TERMTYPE2 tterm;
|
||||||
|
unsigned nuses;
|
||||||
|
ENTRY_USES uses[MAX_USES];
|
||||||
|
int ncrosslinks;
|
||||||
|
ENTRY *crosslinks[MAX_CROSSLINKS];
|
||||||
|
long cstart;
|
||||||
|
long cend;
|
||||||
|
long startline;
|
||||||
|
ENTRY *next;
|
||||||
|
ENTRY *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT_VAR(ENTRY *) _nc_head;
|
||||||
|
extern NCURSES_EXPORT_VAR(ENTRY *) _nc_tail;
|
||||||
|
#define for_entry_list(qp) for (qp = _nc_head; qp; qp = qp->next)
|
||||||
|
#define for_entry_list2(qp,q0) for (qp = q0; qp; qp = qp->next)
|
||||||
|
|
||||||
|
#define MAX_LINE 132
|
||||||
|
|
||||||
|
#define NULLHOOK (bool(*)(ENTRY *))0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that WANTED and PRESENT are not simple inverses! If a capability
|
||||||
|
* has been explicitly cancelled, it is not considered WANTED.
|
||||||
|
*/
|
||||||
|
#define WANTED(s) ((s) == ABSENT_STRING)
|
||||||
|
#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING))
|
||||||
|
|
||||||
|
#define ANDMISSING(p,q) \
|
||||||
|
{ \
|
||||||
|
if (PRESENT(p) && !PRESENT(q)) \
|
||||||
|
_nc_warning(#p " but no " #q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PAIRED(p,q) \
|
||||||
|
{ \
|
||||||
|
if (PRESENT(q) && !PRESENT(p)) \
|
||||||
|
_nc_warning(#q " but no " #p); \
|
||||||
|
if (PRESENT(p) && !PRESENT(q)) \
|
||||||
|
_nc_warning(#p " but no " #q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints are used only by the ncurses utilities such as tic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* alloc_entry.c: elementary allocation code */
|
||||||
|
extern NCURSES_EXPORT(ENTRY *) _nc_copy_entry (ENTRY *oldp);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_save_str (const char *const);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_init_entry (ENTRY *const);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_merge_entry (ENTRY *const, ENTRY *const);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_wrap_entry (ENTRY *const, bool);
|
||||||
|
|
||||||
|
/* alloc_ttype.c: elementary allocation code */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_align_termtype (TERMTYPE2 *, TERMTYPE2 *);
|
||||||
|
|
||||||
|
/* free_ttype.c: elementary allocation code */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_free_termtype1 (TERMTYPE *);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_free_termtype2 (TERMTYPE2 *);
|
||||||
|
|
||||||
|
/* lib_termcap.c: trim sgr0 string for termcap users */
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_trim_sgr0 (TERMTYPE2 *);
|
||||||
|
|
||||||
|
/* parse_entry.c: entry-parsing code */
|
||||||
|
#if NCURSES_XNAMES
|
||||||
|
extern NCURSES_EXPORT_VAR(bool) _nc_user_definable;
|
||||||
|
extern NCURSES_EXPORT_VAR(bool) _nc_disable_period;
|
||||||
|
#endif
|
||||||
|
extern NCURSES_EXPORT(int) _nc_parse_entry (ENTRY *, int, bool);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_capcmp (const char *, const char *);
|
||||||
|
|
||||||
|
/* write_entry.c: writing an entry to the file system */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_set_writedir (const char *);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_write_entry (TERMTYPE2 *const);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_write_object (TERMTYPE2 *, char *, unsigned *, unsigned);
|
||||||
|
|
||||||
|
/* comp_parse.c: entry list handling */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_read_entry_source (FILE*, char*, int, bool, bool (*)(ENTRY*));
|
||||||
|
extern NCURSES_EXPORT(bool) _nc_entry_match (char *, char *);
|
||||||
|
extern NCURSES_EXPORT(int) _nc_resolve_uses (bool); /* obs 20040705 */
|
||||||
|
extern NCURSES_EXPORT(int) _nc_resolve_uses2 (bool, bool);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_free_entries (ENTRY *);
|
||||||
|
extern NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype)(TERMTYPE *); /* obs 20040705 */
|
||||||
|
extern NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype2)(TERMTYPE2 *, bool);
|
||||||
|
|
||||||
|
/* trace_xnames.c */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_trace_xnames (TERMTYPE *);
|
||||||
|
|
||||||
|
#endif /* NCURSES_INTERNALS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints were used by tack before 1.08.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NCURSES_TACK_1_08
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
#define NCURSES_TACK_1_08 /* nothing */
|
||||||
|
#else
|
||||||
|
#define NCURSES_TACK_1_08 GCC_DEPRECATED("upgrade to tack 1.08")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* alloc_ttype.c: elementary allocation code */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_copy_termtype (TERMTYPE *, const TERMTYPE *) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
/* lib_acs.c */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_init_acs (void) NCURSES_TACK_1_08; /* corresponds to traditional 'init_acs()' */
|
||||||
|
|
||||||
|
/* free_ttype.c: elementary allocation code */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_free_termtype (TERMTYPE *) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* NCURSES_TERM_ENTRY_H_incl */
|
|
@ -0,0 +1,73 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018-2020,2021 Thomas E. Dickey *
|
||||||
|
* Copyright 1998-2000,2001 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
||||||
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* $Id: termcap.h.in,v 1.20 2021/06/17 21:26:02 tom Exp $ */
|
||||||
|
|
||||||
|
#ifndef NCURSES_TERMCAP_H_incl
|
||||||
|
#define NCURSES_TERMCAP_H_incl 1
|
||||||
|
|
||||||
|
#undef NCURSES_VERSION
|
||||||
|
#define NCURSES_VERSION "6.4"
|
||||||
|
|
||||||
|
#include <ncurses_dll.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#undef NCURSES_OSPEED
|
||||||
|
#define NCURSES_OSPEED short
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT_VAR(char) PC;
|
||||||
|
extern NCURSES_EXPORT_VAR(char *) UP;
|
||||||
|
extern NCURSES_EXPORT_VAR(char *) BC;
|
||||||
|
extern NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed;
|
||||||
|
|
||||||
|
#if !defined(NCURSES_TERM_H_incl)
|
||||||
|
extern NCURSES_EXPORT(char *) tgetstr (const char *, char **);
|
||||||
|
extern NCURSES_EXPORT(char *) tgoto (const char *, int, int);
|
||||||
|
extern NCURSES_EXPORT(int) tgetent (char *, const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tgetflag (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tgetnum (const char *);
|
||||||
|
extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NCURSES_TERMCAP_H_incl */
|
|
@ -0,0 +1,396 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2018-2021,2022 Thomas E. Dickey *
|
||||||
|
* Copyright 1998-2012,2017 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
||||||
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
||||||
|
* and: Thomas E. Dickey 1996 on *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Id: tic.h,v 1.86 2022/09/17 16:01:45 tom Exp $
|
||||||
|
* tic.h - Global variables and structures for the terminfo compiler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TIC_H
|
||||||
|
#define __TIC_H
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ncurses_cfg.h>
|
||||||
|
|
||||||
|
#include <curses.h> /* for the _tracef() prototype, ERR/OK, bool defs */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The format of SVr2 compiled terminfo files is as follows:
|
||||||
|
**
|
||||||
|
** Header (12 bytes), containing information given below
|
||||||
|
** Names Section, containing the names of the terminal
|
||||||
|
** Boolean Section, containing the values of all of the
|
||||||
|
** boolean capabilities
|
||||||
|
** A null byte may be inserted here to make
|
||||||
|
** sure that the Number Section begins on an
|
||||||
|
** even word boundary.
|
||||||
|
** Number Section, containing the values of all of the numeric
|
||||||
|
** capabilities, each as a short integer
|
||||||
|
** String Section, containing short integer offsets into the
|
||||||
|
** String Table, one per string capability
|
||||||
|
** String Table, containing the actual characters of the string
|
||||||
|
** capabilities.
|
||||||
|
**
|
||||||
|
** In the SVr2 format, "short" means signed 16-bit numbers, which is sometimes
|
||||||
|
** inconvenient. The numbers are signed, to provide for absent and canceled
|
||||||
|
** values. ncurses6.1 introduced an extension to this compiled format, by
|
||||||
|
** making the Number Section a list of signed 32-bit integers.
|
||||||
|
**
|
||||||
|
** NOTE that all short integers in the file are stored using VAX/PDP-style
|
||||||
|
** byte-order, i.e., least-significant byte first.
|
||||||
|
**
|
||||||
|
** There is no structure definition here because it would only confuse
|
||||||
|
** matters. Terminfo format is a raw byte layout, not a structure
|
||||||
|
** dump. If you happen to be on a little-endian machine with 16-bit
|
||||||
|
** shorts that requires no padding between short members in a struct,
|
||||||
|
** then there is a natural C structure that captures the header, but
|
||||||
|
** not very helpfully.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAGIC 0432 /* first two bytes of a compiled entry */
|
||||||
|
#define MAGIC2 01036 /* first two bytes of a compiled 32-bit entry */
|
||||||
|
|
||||||
|
#undef BYTE
|
||||||
|
#define BYTE(p,n) (unsigned char)((p)[n])
|
||||||
|
|
||||||
|
#define IS_NEG1(p) ((BYTE(p,0) == 0377) && (BYTE(p,1) == 0377))
|
||||||
|
#define IS_NEG2(p) ((BYTE(p,0) == 0376) && (BYTE(p,1) == 0377))
|
||||||
|
#define LOW_MSB(p) (BYTE(p,0) + 256*BYTE(p,1))
|
||||||
|
|
||||||
|
#define IS_TIC_MAGIC(p) (LOW_MSB(p) == MAGIC || LOW_MSB(p) == MAGIC2)
|
||||||
|
|
||||||
|
#define quick_prefix(s) (!strncmp((s), "b64:", (size_t)4) || !strncmp((s), "hex:", (size_t)4))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The "maximum" here is misleading; XSI guarantees minimum values, which a
|
||||||
|
* given implementation may exceed.
|
||||||
|
*/
|
||||||
|
#define MAX_NAME_SIZE 512 /* maximum legal name field size (XSI:127) */
|
||||||
|
#define MAX_ENTRY_SIZE1 4096 /* maximum legal entry size (SVr2) */
|
||||||
|
#define MAX_ENTRY_SIZE2 32768 /* maximum legal entry size (ncurses6.1) */
|
||||||
|
|
||||||
|
#if NCURSES_EXT_COLORS && HAVE_INIT_EXTENDED_COLOR
|
||||||
|
#define MAX_ENTRY_SIZE MAX_ENTRY_SIZE2
|
||||||
|
#else
|
||||||
|
#define MAX_ENTRY_SIZE MAX_ENTRY_SIZE1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum size of individual name or alias is guaranteed in XSI to be at
|
||||||
|
* least 14, since that corresponds to the older filename lengths. Newer
|
||||||
|
* systems allow longer aliases, though not many terminal descriptions are
|
||||||
|
* written to use them. The MAX_ALIAS symbol is used for warnings.
|
||||||
|
*/
|
||||||
|
#if HAVE_LONG_FILE_NAMES
|
||||||
|
#define MAX_ALIAS 32 /* smaller than POSIX minimum for PATH_MAX */
|
||||||
|
#else
|
||||||
|
#define MAX_ALIAS 14 /* SVr3 filename length */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* location of user's personal info directory */
|
||||||
|
#define PRIVATE_INFO "%s/.terminfo" /* plug getenv("HOME") into %s */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some traces are designed to be used via tic's verbose option (and similar in
|
||||||
|
* infocmp and toe) rather than the 'trace()' function. So we use the bits
|
||||||
|
* above the normal trace() parameter as a debug-level.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_DEBUG_LEVEL 15
|
||||||
|
#define DEBUG_LEVEL(n) ((n) << TRACE_SHIFT)
|
||||||
|
|
||||||
|
#define set_trace_level(n) \
|
||||||
|
_nc_tracing &= TRACE_MAXIMUM, \
|
||||||
|
_nc_tracing |= DEBUG_LEVEL(n)
|
||||||
|
|
||||||
|
#ifdef TRACE
|
||||||
|
#define DEBUG(n, a) if (_nc_tracing >= DEBUG_LEVEL(n)) _tracef a
|
||||||
|
#else
|
||||||
|
#define DEBUG(n, a) /*nothing*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the types of tokens returned by the scanner. The first
|
||||||
|
* three are also used in the hash table of capability names. The scanner
|
||||||
|
* returns one of these values after loading the specifics into the global
|
||||||
|
* structure curr_token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOOLEAN 0 /* Boolean capability */
|
||||||
|
#define NUMBER 1 /* Numeric capability */
|
||||||
|
#define STRING 2 /* String-valued capability */
|
||||||
|
#define CANCEL 3 /* Capability to be cancelled in following tc's */
|
||||||
|
#define NAMES 4 /* The names for a terminal type */
|
||||||
|
#define UNDEF 5 /* Undefined */
|
||||||
|
|
||||||
|
#define NO_PUSHBACK -1 /* used in pushtype to indicate no pushback */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The global structure in which the specific parts of a
|
||||||
|
* scanned token are returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct token
|
||||||
|
{
|
||||||
|
char *tk_name; /* name of capability */
|
||||||
|
int tk_valnumber; /* value of capability (if a number) */
|
||||||
|
char *tk_valstring; /* value of capability (if a string) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offsets to string capabilities, with the corresponding functionkey codes.
|
||||||
|
*/
|
||||||
|
struct tinfo_fkeys {
|
||||||
|
unsigned offset;
|
||||||
|
chtype code;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef short HashValue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The file comp_captab.c contains an array of these structures, one per
|
||||||
|
* possible capability. These are indexed by a hash table array of pointers to
|
||||||
|
* the same structures for use by the parser.
|
||||||
|
*/
|
||||||
|
struct name_table_entry
|
||||||
|
{
|
||||||
|
const char *nte_name; /* name to hash on */
|
||||||
|
int nte_type; /* BOOLEAN, NUMBER or STRING */
|
||||||
|
HashValue nte_index; /* index of associated variable in its array */
|
||||||
|
HashValue nte_link; /* index in table of next hash, or -1 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use this structure to hide differences between terminfo and termcap tables.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned table_size;
|
||||||
|
const HashValue *table_data;
|
||||||
|
HashValue (*hash_of)(const char *);
|
||||||
|
int (*compare_names)(const char *, const char *);
|
||||||
|
} HashData;
|
||||||
|
|
||||||
|
struct alias
|
||||||
|
{
|
||||||
|
const char *from;
|
||||||
|
const char *to;
|
||||||
|
const char *source;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NOTFOUND ((struct name_table_entry *) 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The file comp_userdefs.c contains an array of these structures, one per
|
||||||
|
* possible capability. These are indexed by a hash table array of pointers to
|
||||||
|
* the same structures for use by the parser.
|
||||||
|
*/
|
||||||
|
struct user_table_entry
|
||||||
|
{
|
||||||
|
const char *ute_name; /* name to hash on */
|
||||||
|
int ute_type; /* mask (BOOLEAN, NUMBER, STRING) */
|
||||||
|
unsigned ute_argc; /* number of parameters */
|
||||||
|
unsigned ute_args; /* bit-mask for string parameters */
|
||||||
|
HashValue ute_index; /* index of associated variable in its array */
|
||||||
|
HashValue ute_link; /* index in table of next hash, or -1 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The casts are required for correct sign-propagation with systems such as
|
||||||
|
* AIX, IRIX64, Solaris which default to unsigned characters. The C standard
|
||||||
|
* leaves this detail unspecified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* out-of-band values for representing absent capabilities */
|
||||||
|
#define ABSENT_BOOLEAN ((signed char)-1) /* 255 */
|
||||||
|
#define ABSENT_NUMERIC (-1)
|
||||||
|
#define ABSENT_STRING (char *)0
|
||||||
|
|
||||||
|
/* out-of-band values for representing cancels */
|
||||||
|
#define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */
|
||||||
|
#define CANCELLED_NUMERIC (-2)
|
||||||
|
#define CANCELLED_STRING (char *)(-1)
|
||||||
|
|
||||||
|
#define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */
|
||||||
|
#define VALID_NUMERIC(s) ((s) >= 0)
|
||||||
|
#define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING)
|
||||||
|
|
||||||
|
/* termcap entries longer than this may break old binaries */
|
||||||
|
#define MAX_TERMCAP_LENGTH 1023
|
||||||
|
|
||||||
|
/* this is a documented limitation of terminfo */
|
||||||
|
#define MAX_TERMINFO_LENGTH 4096
|
||||||
|
|
||||||
|
#ifndef TERMINFO
|
||||||
|
#define TERMINFO "/usr/share/terminfo"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NCURSES_TERM_ENTRY_H_incl
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints are used only by the ncurses utilities such as tic.
|
||||||
|
*/
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
/* access.c */
|
||||||
|
extern NCURSES_EXPORT(unsigned) _nc_pathlast (const char *);
|
||||||
|
extern NCURSES_EXPORT(bool) _nc_is_abs_path (const char *);
|
||||||
|
extern NCURSES_EXPORT(bool) _nc_is_dir_path (const char *);
|
||||||
|
extern NCURSES_EXPORT(bool) _nc_is_file_path (const char *);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_basename (char *);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_rootname (char *);
|
||||||
|
|
||||||
|
/* comp_captab.c */
|
||||||
|
extern NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool);
|
||||||
|
extern NCURSES_EXPORT(const HashData *) _nc_get_hash_info (bool);
|
||||||
|
extern NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool);
|
||||||
|
|
||||||
|
/* comp_hash.c: name lookup */
|
||||||
|
extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_type_entry
|
||||||
|
(const char *, int, bool);
|
||||||
|
extern NCURSES_EXPORT(struct user_table_entry const *) _nc_find_user_entry
|
||||||
|
(const char *);
|
||||||
|
|
||||||
|
/* comp_scan.c: lexical analysis */
|
||||||
|
extern NCURSES_EXPORT(int) _nc_get_token (bool);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_panic_mode (char);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_push_token (int);
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_curr_col;
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_curr_line;
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_syntax;
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_strict_bsd;
|
||||||
|
extern NCURSES_EXPORT_VAR(long) _nc_comment_end;
|
||||||
|
extern NCURSES_EXPORT_VAR(long) _nc_comment_start;
|
||||||
|
extern NCURSES_EXPORT_VAR(long) _nc_curr_file_pos;
|
||||||
|
extern NCURSES_EXPORT_VAR(long) _nc_start_line;
|
||||||
|
#define SYN_TERMINFO 0
|
||||||
|
#define SYN_TERMCAP 1
|
||||||
|
|
||||||
|
/* comp_error.c: warning & abort messages */
|
||||||
|
extern NCURSES_EXPORT(const char *) _nc_get_source (void);
|
||||||
|
extern GCC_NORETURN NCURSES_EXPORT(void) _nc_err_abort (const char *const,...) GCC_PRINTFLIKE(1,2);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_get_type (char *name);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_set_source (const char *const);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_set_type (const char *const);
|
||||||
|
extern GCC_NORETURN NCURSES_EXPORT(void) _nc_syserr_abort (const char *const,...) GCC_PRINTFLIKE(1,2);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_warning (const char *const,...) GCC_PRINTFLIKE(1,2);
|
||||||
|
extern NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings;
|
||||||
|
|
||||||
|
/* comp_scan.c */
|
||||||
|
extern NCURSES_EXPORT_VAR(struct token) _nc_curr_token;
|
||||||
|
|
||||||
|
/* comp_userdefs.c */
|
||||||
|
NCURSES_EXPORT(const struct user_table_entry *) _nc_get_userdefs_table (void);
|
||||||
|
NCURSES_EXPORT(const HashData *) _nc_get_hash_user (void);
|
||||||
|
|
||||||
|
/* captoinfo.c: capability conversion */
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_captoinfo (const char *, const char *, int const);
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_infotocap (const char *, const char *, int const);
|
||||||
|
|
||||||
|
/* home_terminfo.c */
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_home_terminfo (void);
|
||||||
|
|
||||||
|
/* init_keytry.c */
|
||||||
|
#if BROKEN_LINKER
|
||||||
|
#define _nc_tinfo_fkeys _nc_tinfo_fkeysf()
|
||||||
|
extern NCURSES_EXPORT(const struct tinfo_fkeys *) _nc_tinfo_fkeysf (void);
|
||||||
|
#else
|
||||||
|
extern NCURSES_EXPORT_VAR(const struct tinfo_fkeys) _nc_tinfo_fkeys[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* lib_tparm.c */
|
||||||
|
#define NUM_PARM 9
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_tparm_err;
|
||||||
|
|
||||||
|
extern NCURSES_EXPORT(int) _nc_tparm_analyze(TERMINAL *, const char *, char **, int *);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_reset_tparm(TERMINAL *);
|
||||||
|
|
||||||
|
/* lib_trace.c */
|
||||||
|
extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing;
|
||||||
|
extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *);
|
||||||
|
extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *);
|
||||||
|
|
||||||
|
/* lib_tputs.c */
|
||||||
|
extern NCURSES_EXPORT_VAR(int) _nc_nulls_sent; /* Add one for every null sent */
|
||||||
|
|
||||||
|
/* comp_main.c: compiler main */
|
||||||
|
extern const char * _nc_progname;
|
||||||
|
|
||||||
|
/* db_iterator.c */
|
||||||
|
extern NCURSES_EXPORT(const char *) _nc_next_db(DBDIRS *, int *);
|
||||||
|
extern NCURSES_EXPORT(const char *) _nc_tic_dir (const char *);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_first_db(DBDIRS *, int *);
|
||||||
|
extern NCURSES_EXPORT(void) _nc_last_db(void);
|
||||||
|
|
||||||
|
/* write_entry.c */
|
||||||
|
extern NCURSES_EXPORT(int) _nc_tic_written (void);
|
||||||
|
|
||||||
|
#endif /* NCURSES_INTERNALS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These entrypoints were used by tack before 1.08.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NCURSES_TACK_1_08
|
||||||
|
#ifdef NCURSES_INTERNALS
|
||||||
|
#define NCURSES_TACK_1_08 /* nothing */
|
||||||
|
#else
|
||||||
|
#define NCURSES_TACK_1_08 GCC_DEPRECATED("upgrade to tack 1.08")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* comp_hash.c: name lookup */
|
||||||
|
extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_entry
|
||||||
|
(const char *, const HashValue *) NCURSES_TACK_1_08;
|
||||||
|
extern NCURSES_EXPORT(const HashValue *) _nc_get_hash_table (bool) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
/* comp_scan.c: lexical analysis */
|
||||||
|
extern NCURSES_EXPORT(void) _nc_reset_input (FILE *, char *) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
/* comp_expand.c: expand string into readable form */
|
||||||
|
extern NCURSES_EXPORT(char *) _nc_tic_expand (const char *, bool, int) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
/* comp_scan.c: decode string from readable form */
|
||||||
|
extern NCURSES_EXPORT(int) _nc_trans_string (char *, char *) NCURSES_TACK_1_08;
|
||||||
|
|
||||||
|
#endif /* NCURSES_TERM_ENTRY_H_incl */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
#endif /* __TIC_H */
|
|
@ -0,0 +1,68 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright 2020 Thomas E. Dickey *
|
||||||
|
* Copyright 1998-2001,2009 Free Software Foundation, Inc. *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the *
|
||||||
|
* "Software"), to deal in the Software without restriction, including *
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||||
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||||
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
* Except as contained in this notice, the name(s) of the above copyright *
|
||||||
|
* holders shall not be used in advertising or otherwise to promote the *
|
||||||
|
* sale, use or other dealings in this Software without prior written *
|
||||||
|
* authorization. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
||||||
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unctrl.h
|
||||||
|
*
|
||||||
|
* Display a printable version of a control character.
|
||||||
|
* Control characters are displayed in caret notation (^x), DELETE is displayed
|
||||||
|
* as ^?. Printable characters are displayed as is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: unctrl.h.in,v 1.12 2020/02/02 23:34:34 tom Exp $ */
|
||||||
|
|
||||||
|
#ifndef NCURSES_UNCTRL_H_incl
|
||||||
|
#define NCURSES_UNCTRL_H_incl 1
|
||||||
|
|
||||||
|
#undef NCURSES_VERSION
|
||||||
|
#define NCURSES_VERSION "6.4"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
|
#undef unctrl
|
||||||
|
NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NCURSES_UNCTRL_H_incl */
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,4 @@
|
||||||
|
ncurses库版本6.4,未做任何修改。
|
||||||
|
应用笔记:http://chenyf123.top:1050/2024/04/10/ncurses%e5%ba%93%e8%b0%83%e8%af%95/
|
||||||
|
源码:http://chenyf123.top:1000/#s/-Tu65hXw
|
||||||
|
arm-linux-gnueabihf 版本release : http://chenyf123.top:1000/#s/-Tu9gtVQ
|
|
@ -0,0 +1,702 @@
|
||||||
|
/** function comment
|
||||||
|
* @Author: 陈逸凡 1343619937@qq.com
|
||||||
|
* @Date: 2024-04-08 14:56:56
|
||||||
|
* @LastEditors: 陈逸凡 1343619937@qq.com
|
||||||
|
* @LastEditTime: 2024-04-24 10:14:02
|
||||||
|
* @FilePath: \run\run.c
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
#include "ncurses.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include "shell.h"
|
||||||
|
#include "shellcmd.h"
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
// typedef struct SHELL_OBJ
|
||||||
|
// {
|
||||||
|
int row = 0;
|
||||||
|
int scr_row, scr_col = 0;
|
||||||
|
// shell输入缓冲区
|
||||||
|
char input[SHELL_COMMAND_MAX_LENGTH];
|
||||||
|
int input_pos = 0; // 当前输入位置
|
||||||
|
// shell命令提示符
|
||||||
|
char prompt[30] = {0};
|
||||||
|
// shell命令列表
|
||||||
|
// SHELL_CommandTypeDef *shellCommandList;
|
||||||
|
// shell命令历史记录
|
||||||
|
char inputHistory[SHELL_HISTORY_MAX_NUMBER][SHELL_COMMAND_MAX_LENGTH];
|
||||||
|
// shell命令历史记录数量
|
||||||
|
int inputHistoryCount = 0;
|
||||||
|
|
||||||
|
char screen_choose = 0;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SCREEN_SHELL = 0b01,
|
||||||
|
SCREEN_TELNET = 0b10,
|
||||||
|
} SCREEN_CHOOSE;
|
||||||
|
// } SHELL_OBJ; // shell命令定义
|
||||||
|
// SHELL_OBJ obj;
|
||||||
|
|
||||||
|
static uint8_t shellHistoryCommand[SHELL_HISTORY_MAX_NUMBER][SHELL_COMMAND_MAX_LENGTH] = {0};
|
||||||
|
static uint8_t shellHistoryCount = 0; // 已记录的历史命令数量
|
||||||
|
/*
|
||||||
|
shell的历史记录参数linux shell的历史记录控制逻辑
|
||||||
|
shellHistoryFlag = -1 认为是输入模式,不显示历史记录
|
||||||
|
shellHistoryFlag = 0 认为是显示最新的历史记录
|
||||||
|
依次类推
|
||||||
|
当 shellHistoryFlag = 0时,按下下键,进入输入模式,shellHistoryFlag = -1
|
||||||
|
输入模式下命令不会被记录,所以会清除掉所有输入的命令
|
||||||
|
*/
|
||||||
|
static signed char shellHistoryFlag = 0; // 当前记录位置
|
||||||
|
static signed char shellHistoryOffset = 0;
|
||||||
|
|
||||||
|
const SHELL_CommandTypeDef shellCommandList[] =
|
||||||
|
{
|
||||||
|
/*command function description*/
|
||||||
|
{"letter", shellLetter, "letter shell"},
|
||||||
|
{"letter2", shellLetter, "letter shell"},
|
||||||
|
{"letter3", shellLetter, "letter shell"},
|
||||||
|
{"test", shellFunTest, "letter shell"},
|
||||||
|
// {"reboot", shellReboot, "reboot system"},
|
||||||
|
{"help", shellShowCommandList, "show command list"},
|
||||||
|
{"ls", shellShowCommandList, "show command list"},
|
||||||
|
{"clear", shellClear, "clear command line"},
|
||||||
|
|
||||||
|
// #if SHELL_USE_PARAMETER == 1 /*带参函数命令*/
|
||||||
|
// {(uint8_t *)"list_thread", (void (*)())list_thread, (uint8_t *)"list_thread"},
|
||||||
|
{"can_status", can_status, "can_status"},
|
||||||
|
{"show_net_node", show_net_node, "show_net_node"},
|
||||||
|
// {"alloc_mem_total", (void (*)())alloc_mem_total, (uint8_t *)"alloc_mem_total"},
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
int charcmp(char *str1, char *str2, int len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (str1[i] != str2[i])
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_completion_searh(char *c)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
if (charcmp(c, shellCommandList[i].name, strlen(c)))
|
||||||
|
{
|
||||||
|
printw("%s\n", shellCommandList[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shellShowCommandList(char *args)
|
||||||
|
{
|
||||||
|
print_all("\nCOMMAND FUNCTION\n----------------------------------------\n");
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
print_all("%s : %s\n", shellCommandList[i].name, shellCommandList[i].desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void shellLetter(char *args)
|
||||||
|
{
|
||||||
|
// shellDisplay("Letter shell " SHELL_VERSION "\r\n");
|
||||||
|
// shellDisplay("(C) Copyright 2018 Leter, All Right Reserved\r\n");
|
||||||
|
print_all("\nliter");
|
||||||
|
}
|
||||||
|
char *getArg(char *input, char *output)
|
||||||
|
{
|
||||||
|
char string_state = 0;
|
||||||
|
// 去头
|
||||||
|
while (*input != '\0' && *input == ' ')
|
||||||
|
{
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
while (*input != '\0')
|
||||||
|
{
|
||||||
|
if (*input == '\'' || *input == '\"')
|
||||||
|
{
|
||||||
|
string_state = !string_state;
|
||||||
|
input++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (string_state)
|
||||||
|
{
|
||||||
|
*output = *input;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*input == ' ' || *input == ',')
|
||||||
|
{
|
||||||
|
// 给下次判断用,需要自增
|
||||||
|
input++;
|
||||||
|
*output = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*output = *input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input++;
|
||||||
|
output++;
|
||||||
|
}
|
||||||
|
// 不管while是否执行,output一定要加'\0
|
||||||
|
*output = '\0';
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ana_float(char *arg)
|
||||||
|
{
|
||||||
|
while (*arg == ' ')
|
||||||
|
{
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
char point = 0;
|
||||||
|
int v_int = 0;
|
||||||
|
int v_p_float = 0;
|
||||||
|
float v_p_float_f = 0;
|
||||||
|
while (*arg != '\0')
|
||||||
|
{
|
||||||
|
// print_all("%c", *arg);
|
||||||
|
if ((*arg < '0' || *arg > '9') && *arg != '.')
|
||||||
|
{
|
||||||
|
v_int = 0;
|
||||||
|
v_p_float = 0;
|
||||||
|
print_all("error float: %d\n", *arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*arg == '.')
|
||||||
|
{
|
||||||
|
point = 1;
|
||||||
|
arg++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (point)
|
||||||
|
{
|
||||||
|
v_p_float = v_p_float * 10 + (*arg - '0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v_int = v_int * 10 + (*arg - '0');
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
print_all("v_int = %d\n", v_int);
|
||||||
|
print_all("v_p_float = %d\n", v_p_float);
|
||||||
|
v_p_float_f = v_p_float;
|
||||||
|
while (v_p_float_f > 1.0)
|
||||||
|
{
|
||||||
|
v_p_float_f = v_p_float_f / 10.0;
|
||||||
|
}
|
||||||
|
print_all("v_p_float_f = %f\n", v_p_float_f);
|
||||||
|
if (v_p_float_f == 0.0)
|
||||||
|
{
|
||||||
|
print_all("error float: %f\n", v_p_float_f);
|
||||||
|
}
|
||||||
|
float result = (float)v_int + v_p_float_f;
|
||||||
|
printw("result = %f\n", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shellReboot(char *args)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
extern void telnet_put_char(char c);
|
||||||
|
telnet_put_char('\f');
|
||||||
|
}
|
||||||
|
void shellClear(char *args)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
extern void telnet_put_char(char c);
|
||||||
|
telnet_put_char('\f');
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_auto_completion_for_telnet(void)
|
||||||
|
{
|
||||||
|
#include "telnet.h"
|
||||||
|
extern void telnet_put_char(char c);
|
||||||
|
extern void telnet_send_string(char *c, int len);
|
||||||
|
extern telnet_t *get_telnet_obj();
|
||||||
|
telnet_t *tel = get_telnet_obj();
|
||||||
|
if (tel == NULL || tel->init == 0 || tel->login_in == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tel->cmd_pos == 0)
|
||||||
|
{
|
||||||
|
char cmd[] = "help";
|
||||||
|
for (int i = 0; i < (sizeof(cmd) - 1); i++)
|
||||||
|
{
|
||||||
|
tel->cmd_buff[tel->cmd_pos++] = cmd[i];
|
||||||
|
}
|
||||||
|
telnet_send_string(cmd, strlen(cmd));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int match_num = 0;
|
||||||
|
int match = 0;
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
for (int j = 0; j < tel->cmd_pos; j++)
|
||||||
|
{
|
||||||
|
if (tel->cmd_buff[j] != shellCommandList[i].name[j])
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
match_num = i;
|
||||||
|
match++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match == 1 && tel->table_mode & 1)
|
||||||
|
{
|
||||||
|
for (int i = tel->cmd_pos; i < SHELL_COMMAND_MAX_LENGTH; i++)
|
||||||
|
{
|
||||||
|
if (shellCommandList[match_num].name[i] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tel->cmd_buff[tel->cmd_pos++] = shellCommandList[match_num].name[i];
|
||||||
|
telnet_put_char(shellCommandList[match_num].name[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match > 1 && tel->table_mode & 2)
|
||||||
|
{
|
||||||
|
unsigned char cmd[] = {27, 91, 66};
|
||||||
|
telnet_send_string(cmd, 3);
|
||||||
|
telnet_put_char('\r');
|
||||||
|
// 再做一遍循环
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
for (int j = 0; j < tel->cmd_pos; j++)
|
||||||
|
{
|
||||||
|
if (tel->cmd_buff[j] != shellCommandList[i].name[j])
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < SHELL_COMMAND_MAX_LENGTH; j++)
|
||||||
|
{
|
||||||
|
if (shellCommandList[i].name[j] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
telnet_put_char(shellCommandList[i].name[j]);
|
||||||
|
}
|
||||||
|
telnet_put_char(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd[2] = 65;
|
||||||
|
telnet_send_string(cmd, 3);
|
||||||
|
telnet_put_char('\r');
|
||||||
|
char *prompt = tel->tel_prompt;
|
||||||
|
while (*prompt != '\0')
|
||||||
|
{
|
||||||
|
telnet_put_char(*prompt);
|
||||||
|
prompt++;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < tel->cmd_pos; j++)
|
||||||
|
{
|
||||||
|
telnet_put_char(tel->cmd_buff[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->table_mode |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_auto_completion(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
telnetl shell 不适合使用这套机制,需要重新rewrite
|
||||||
|
*/
|
||||||
|
if (input_pos == 0)
|
||||||
|
{
|
||||||
|
char cmd[] = "help";
|
||||||
|
for (int i = 0; i < (sizeof(cmd) - 1); i++)
|
||||||
|
{
|
||||||
|
printw("%c", cmd[i]);
|
||||||
|
input[input_pos++] = cmd[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char part[PART_SIZE(shellCommandList)] = {0};
|
||||||
|
int match = 0;
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
char check = 1;
|
||||||
|
for (int j = 0; j < input_pos; j++)
|
||||||
|
{
|
||||||
|
if (input[j] != shellCommandList[i].name[j])
|
||||||
|
{
|
||||||
|
check = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (check)
|
||||||
|
{
|
||||||
|
match++;
|
||||||
|
part[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match == 1)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (; i < PART_SIZE(shellCommandList); i++)
|
||||||
|
{
|
||||||
|
if (part[i] == 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int pos = input_pos;
|
||||||
|
while (shellCommandList[i].name[pos] != '\0')
|
||||||
|
{
|
||||||
|
printw("%c", shellCommandList[i].name[pos]);
|
||||||
|
input[pos] = shellCommandList[i].name[pos];
|
||||||
|
pos++;
|
||||||
|
input_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get current x,y
|
||||||
|
int x, y = 0;
|
||||||
|
getyx(stdscr, y, x);
|
||||||
|
//
|
||||||
|
printw("\n");
|
||||||
|
printw("match: ");
|
||||||
|
if (match > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < PART_SIZE(shellCommandList); i++)
|
||||||
|
{
|
||||||
|
if (part[i] == 1)
|
||||||
|
{
|
||||||
|
printw("%s ", shellCommandList[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printw("null");
|
||||||
|
}
|
||||||
|
if (y < scr_row - 1)
|
||||||
|
{
|
||||||
|
move(y, x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move(y - 1, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// printw("match = %d\n", match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_handle(char *c)
|
||||||
|
{
|
||||||
|
if (c[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ret = 1;
|
||||||
|
for (int i = 0; i < sizeof(shellCommandList) / sizeof(SHELL_CommandTypeDef); i++)
|
||||||
|
{
|
||||||
|
char result = 1;
|
||||||
|
for (int j = 0; j < SHELL_COMMAND_MAX_LENGTH; j++)
|
||||||
|
{
|
||||||
|
if (c[j] == '\0' || c[j] == ' ')
|
||||||
|
{
|
||||||
|
if (shellCommandList[i].name[j] != '\0')
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c[j] != shellCommandList[i].name[j])
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == 1)
|
||||||
|
{
|
||||||
|
shellCommandList[i].function(c);
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
print_all("\nunknow commond:%s", c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void shell_save_history()
|
||||||
|
{
|
||||||
|
if (input[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = SHELL_HISTORY_MAX_NUMBER - 2; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
while (shellHistoryCommand[i][j] != '\0')
|
||||||
|
{
|
||||||
|
shellHistoryCommand[i + 1][j] = shellHistoryCommand[i][j];
|
||||||
|
j++;
|
||||||
|
// avoid died while
|
||||||
|
if (j == SHELL_COMMAND_MAX_LENGTH - 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shellHistoryCommand[i + 1][j] = '\0';
|
||||||
|
}
|
||||||
|
int j = 0;
|
||||||
|
while (input[j] != '\0')
|
||||||
|
{
|
||||||
|
shellHistoryCommand[0][j] = input[j];
|
||||||
|
j++;
|
||||||
|
if (j == SHELL_COMMAND_MAX_LENGTH - 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shellHistoryCommand[0][j] = '\0';
|
||||||
|
}
|
||||||
|
void shell_show_last_history()
|
||||||
|
{
|
||||||
|
if (shellHistoryFlag < SHELL_HISTORY_MAX_NUMBER - 1)
|
||||||
|
{
|
||||||
|
shellHistoryFlag++;
|
||||||
|
int x, y = 0;
|
||||||
|
getyx(stdscr, y, x);
|
||||||
|
move(y, 0);
|
||||||
|
clrtoeol(); // 清除从光标位置到行尾的所有内容
|
||||||
|
printw(prompt);
|
||||||
|
char result = 0;
|
||||||
|
for (int i = 0; i < SHELL_COMMAND_MAX_LENGTH; i++)
|
||||||
|
{
|
||||||
|
if (shellHistoryCommand[shellHistoryFlag][i] == '\0')
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
printf("result = %d\n", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printw(shellHistoryCommand[shellHistoryFlag]);
|
||||||
|
int j = 0;
|
||||||
|
input_pos = 0;
|
||||||
|
while (shellHistoryCommand[shellHistoryFlag][j] != '\0')
|
||||||
|
{
|
||||||
|
input[j] = shellHistoryCommand[shellHistoryFlag][j];
|
||||||
|
j++;
|
||||||
|
input_pos++;
|
||||||
|
if (j == SHELL_COMMAND_MAX_LENGTH - 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_show_next_history()
|
||||||
|
{
|
||||||
|
if (shellHistoryFlag > 0)
|
||||||
|
{
|
||||||
|
shellHistoryFlag--;
|
||||||
|
// printw("\nshellHistoryFlag = %d\n", shellHistoryFlag);
|
||||||
|
// return;
|
||||||
|
int x, y = 0;
|
||||||
|
getyx(stdscr, y, x);
|
||||||
|
move(y, 0);
|
||||||
|
clrtoeol(); // 清除从光标位置到行尾的所有内容
|
||||||
|
refresh();
|
||||||
|
printw(prompt);
|
||||||
|
printw(shellHistoryCommand[shellHistoryFlag]);
|
||||||
|
int j = 0;
|
||||||
|
input_pos = 0;
|
||||||
|
while (shellHistoryCommand[shellHistoryFlag][j] != '\0')
|
||||||
|
{
|
||||||
|
input[j] = shellHistoryCommand[shellHistoryFlag][j];
|
||||||
|
j++;
|
||||||
|
input_pos++;
|
||||||
|
if (j == SHELL_COMMAND_MAX_LENGTH - 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
// shellHistoryFlag++;
|
||||||
|
}
|
||||||
|
else if (shellHistoryFlag == 0)
|
||||||
|
{
|
||||||
|
// printw("\nshellHistoryFlag = %d\n", shellHistoryFlag);
|
||||||
|
shellHistoryFlag--;
|
||||||
|
int x, y = 0;
|
||||||
|
getyx(stdscr, y, x);
|
||||||
|
move(y, 0);
|
||||||
|
clrtoeol(); // 清除从光标位置到行尾的所有内容
|
||||||
|
printw(prompt);
|
||||||
|
refresh();
|
||||||
|
input_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
void printp(char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vwprintw(stdscr, format, args);
|
||||||
|
va_end(args);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 按需打印
|
||||||
|
* screen_choose & SCREEN_SHELL -> shell print
|
||||||
|
* screen_choose & SCREEN_TELNET -> telnet print
|
||||||
|
* 默认shell的打到shell上,telnet打到telnet上
|
||||||
|
* 打印 float 类型有问题,需要打印则先用sprintf将float转换为string然后再通过%s输出
|
||||||
|
*/
|
||||||
|
void print_all(char *format, ...)
|
||||||
|
{
|
||||||
|
if (!is_shell_init())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format); // 初始化参数列表
|
||||||
|
char buff[1024];
|
||||||
|
vsnprintf(buff, sizeof(buff), format, args); // 使用 format 格式化输出
|
||||||
|
va_end(args); // 清理参数列表
|
||||||
|
// 使用 vprintf 函数,它接受一个 va_list 类型的参数列表
|
||||||
|
// vwprintw(stdscr, format, args);
|
||||||
|
va_end(args); // 清理参数列表
|
||||||
|
if (screen_choose & SCREEN_SHELL)
|
||||||
|
{
|
||||||
|
printw(buff);
|
||||||
|
}
|
||||||
|
if (screen_choose & SCREEN_TELNET)
|
||||||
|
{
|
||||||
|
extern void telnet_send_string(char *c, int len);
|
||||||
|
telnet_send_string(buff, strlen(buff));
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
int shell_init_flag = 0;
|
||||||
|
int is_shell_init()
|
||||||
|
{
|
||||||
|
return shell_init_flag;
|
||||||
|
}
|
||||||
|
void *shell_thread_handle(void *args)
|
||||||
|
{
|
||||||
|
initscr(); // 初始化屏幕
|
||||||
|
cbreak(); // 禁用行缓冲
|
||||||
|
keypad(stdscr, TRUE); // 启用键盘输入
|
||||||
|
noecho(); // 不显示输入字符
|
||||||
|
|
||||||
|
getmaxyx(stdscr, scr_row, scr_col);
|
||||||
|
|
||||||
|
sprintf(prompt, "%s(%d,%d)~# ", "quaero@admin", scr_row, scr_col);
|
||||||
|
row++;
|
||||||
|
clear(); // 清除屏幕
|
||||||
|
mvprintw(0, 0, "+=========================================================+\n"); // 在屏幕左上角打印提示符
|
||||||
|
mvprintw(1, 0, "| (C) COPYRIGHT 2018 Letter |\n"); // 在屏幕左上角打印提示符
|
||||||
|
mvprintw(2, 0, "| Letter shell 1.0.0.0 |\n"); // 在屏幕左上角打印提示符
|
||||||
|
mvprintw(3, 0, "+=========================================================+\n"); // 在屏幕左上角打印提示符
|
||||||
|
mvprintw(4, 0, prompt); // 在屏幕左上角打印提示符
|
||||||
|
refresh(); // 刷新屏幕
|
||||||
|
scrollok(stdscr, TRUE); // 允许滚动
|
||||||
|
// scrollok(stdscr, TRUE); // 启用滚动
|
||||||
|
// echo(); // 临时启用回显,以便用户可以看到他们输入的内容
|
||||||
|
// noecho(); // 再次禁用回显
|
||||||
|
// mvprintw(0,0,"+=========================================================+\r\n");
|
||||||
|
// printw("| (C) COPYRIGHT 2018 Letter |\r\n");
|
||||||
|
// printw("+=========================================================+\r\n");
|
||||||
|
shell_init_flag = 1;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int ch = getch(); // 获取用户输入的字符
|
||||||
|
// printw("ch = %d\n", ch);
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '\n': // 换行键,结束输入
|
||||||
|
input[input_pos] = '\0';
|
||||||
|
screen_choose = SCREEN_SHELL;
|
||||||
|
key_handle(input);
|
||||||
|
printw("\n");
|
||||||
|
printw(prompt);
|
||||||
|
input_pos = 0;
|
||||||
|
refresh();
|
||||||
|
shellHistoryFlag = -1;
|
||||||
|
shell_save_history();
|
||||||
|
break;
|
||||||
|
case 9: // Tab 键,尝试补全
|
||||||
|
{
|
||||||
|
shell_auto_completion();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
shell_show_last_history();
|
||||||
|
break;
|
||||||
|
case KEY_DOWN:
|
||||||
|
shell_show_next_history();
|
||||||
|
break;
|
||||||
|
// 127也是退格键
|
||||||
|
case 127:
|
||||||
|
case KEY_BACKSPACE: // 回退键,删除一个字符
|
||||||
|
// printf("backspace\n");
|
||||||
|
if (input_pos > 0)
|
||||||
|
{
|
||||||
|
input_pos--;
|
||||||
|
int x, y = 0;
|
||||||
|
getyx(stdscr, y, x);
|
||||||
|
mvprintw(y, x - 1, " ");
|
||||||
|
move(y, x - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ERR: // 超时或其他错误
|
||||||
|
break;
|
||||||
|
default: // 普通字符,添加到输入中
|
||||||
|
if (ch >= ' ' && ch <= '~' && input_pos < SHELL_COMMAND_MAX_LENGTH - 1)
|
||||||
|
{
|
||||||
|
printw("%c", ch);
|
||||||
|
input[input_pos++] = ch;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endwin(); // 结束ncurses模式
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/** function comment
|
||||||
|
* @Author: 陈逸凡 1343619937@qq.com
|
||||||
|
* @Date: 2024-04-02 13:45:24
|
||||||
|
* @LastEditors: 陈逸凡 1343619937@qq.com
|
||||||
|
* @LastEditTime: 2024-04-23 10:32:33
|
||||||
|
* @FilePath: \com.quaero.soc.fluorescence\module\common\shell\src\shellcmd.c
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "shellcmd.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "libthread.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
/** function comment
|
||||||
|
* @description: shell init function
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
void shell_init(void)
|
||||||
|
{
|
||||||
|
extern void *shell_thread_handle(void *args);
|
||||||
|
extern void *telnet_thread_handle(void *args);
|
||||||
|
pthread_t thread_id;
|
||||||
|
int rc = pthread_create(&thread_id, NULL, shell_thread_handle, NULL);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
printf("Error: shell init error %d\n", rc);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rc = pthread_create(&thread_id, NULL, telnet_thread_handle, NULL);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
printf("Error: telnet shell init error %d\n", rc);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shellFunTest(char *arg_s)
|
||||||
|
{
|
||||||
|
char arg[100];
|
||||||
|
// 搜索头部
|
||||||
|
searchChar(arg_s);
|
||||||
|
//
|
||||||
|
// printw("%s",arg_s);
|
||||||
|
// 获取函数名
|
||||||
|
arg_s = getArg(arg_s, arg);
|
||||||
|
print_all("\narg:%s\n", arg);
|
||||||
|
// 获取inter
|
||||||
|
arg_s = getArg(arg_s, arg);
|
||||||
|
int v_int = atoi(arg);
|
||||||
|
print_all("get inter :%d\n" , v_int);
|
||||||
|
// 获取float,print_all无法用%f打印,先转成字符串再输出
|
||||||
|
arg_s = getArg(arg_s, arg);
|
||||||
|
float v_f = atof(arg);
|
||||||
|
char buff[30];
|
||||||
|
sprintf(buff, "%f", v_f);
|
||||||
|
print_all("get float :%s\n", buff);
|
||||||
|
// 获取字符串
|
||||||
|
arg_s = getArg(arg_s, arg);
|
||||||
|
print_all("get string :%s\n", arg);
|
||||||
|
// print_all("arg:%s\n", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void show_can_device_status(uint32_t channelId, char *output);
|
||||||
|
void can_status(char *args)
|
||||||
|
{
|
||||||
|
char *string[1024] = {0};
|
||||||
|
show_can_device_status(0, string);
|
||||||
|
print_all("\n%s\n", string);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void showNode(INT8U showType, char *output);
|
||||||
|
void show_net_node(char *args)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if ((defined BUS_INTERNET_ENABLE) && (BUS_INTERNET_ENABLE == 1))
|
||||||
|
char *string[1024] = {0};
|
||||||
|
showNode(0, string);
|
||||||
|
print_all("\n%s\n", string);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INT32U bus_mem_total(void);
|
||||||
|
int32_t alloc_mem_total(uint32_t argc, uint8_t *argv[])
|
||||||
|
{
|
||||||
|
printf("memtotal: %d \r\n", bus_mem_total());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,682 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "telnet.h"
|
||||||
|
|
||||||
|
telnet_t telnet = {
|
||||||
|
.passwd = PASSWD,
|
||||||
|
.tel_prompt = TEL_PROMPT,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
telnet_t *get_telnet_obj()
|
||||||
|
{
|
||||||
|
return &telnet;
|
||||||
|
}
|
||||||
|
extern char screen_choose;
|
||||||
|
#define SHOW_IN_TELNET() screen_choose = 2;
|
||||||
|
#define SHOW_IN_SHELL() screen_choose = 1;
|
||||||
|
#define SHOW_IN_ALL() screen_choose = 3;
|
||||||
|
|
||||||
|
int telnet_init(telnet_t *tel, int port)
|
||||||
|
{
|
||||||
|
int telnet_addr_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
// server socket create
|
||||||
|
tel->sock_server = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (tel->sock_server < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: opening socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// server socket set
|
||||||
|
int keepalive = 1;
|
||||||
|
if (setsockopt(tel->sock_server, SOL_SOCKET, SO_REUSEADDR, (void *)&keepalive, sizeof(keepalive)) < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet:set socket keepalive failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// server socket bind and start listen
|
||||||
|
tel->server_addr.sin_family = AF_INET;
|
||||||
|
tel->server_addr.sin_port = htons(port);
|
||||||
|
tel->server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
if (bind(tel->sock_server, (void *)&tel->server_addr, sizeof(tel->server_addr)))
|
||||||
|
{
|
||||||
|
debug_print("error: binding tcp socket ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (listen(tel->sock_server, 1) == -1)
|
||||||
|
{
|
||||||
|
debug_print("error: listen");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
debug_print("telnet: telnet server init success\n");
|
||||||
|
tel->init = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define send_will(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = WILL; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_wont(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = WONT; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_do(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = DO; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_dont(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = DONT; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
|
||||||
|
int read_terminal_type(telnet_t *tel)
|
||||||
|
{
|
||||||
|
unsigned char terminal[] = {IAC, SB, TELOPT_TTYPE, 1, IAC, SE};
|
||||||
|
send(tel->sock_client, terminal, sizeof(terminal), 0);
|
||||||
|
sleep(1);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
if (tel->rec_len < 0)
|
||||||
|
{
|
||||||
|
debug_print("error \n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void histroy_last(telnet_t *tel)
|
||||||
|
{
|
||||||
|
// char a = tel->history_pos + '0';
|
||||||
|
// send(tel->sock_client, &a, 1, 0);
|
||||||
|
// tel->history_pos++;
|
||||||
|
// a = tel->history_pos + '0';
|
||||||
|
// send(tel->sock_client, &a, 1, 0);
|
||||||
|
|
||||||
|
if (tel->history_pos == 255 || (tel->history_pos < (CMD_HISTERY_NUMBER - 1) && (tel->history_pos != 255)))
|
||||||
|
{
|
||||||
|
// // 如果下一个为空则不处理
|
||||||
|
// if (tel->cmd_history[tel->history_pos + 1][0] == 0)
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (tel->history_pos == 255)
|
||||||
|
{
|
||||||
|
if (tel->history_total == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tel->history_pos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((tel->history_pos + 1) >= tel->history_total)
|
||||||
|
return 0;
|
||||||
|
tel->history_pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tel->cmd_pos = 0;
|
||||||
|
for (int i = 0; i < CMD_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (tel->cmd_history[tel->history_pos][i] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tel->cmd_buff[i] = tel->cmd_history[tel->history_pos][i];
|
||||||
|
tel->cmd_pos++;
|
||||||
|
}
|
||||||
|
unsigned char clear_line[] = "\r\033[K";
|
||||||
|
send(tel->sock_client, clear_line, sizeof(clear_line), 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
send(tel->sock_client, tel->cmd_buff, tel->cmd_pos, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void histroy_next(telnet_t *tel)
|
||||||
|
{
|
||||||
|
if (tel->history_pos > 0 && tel->history_pos != 255)
|
||||||
|
{
|
||||||
|
tel->history_pos--;
|
||||||
|
tel->cmd_pos = 0;
|
||||||
|
for (int i = 0; i < CMD_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (tel->cmd_history[tel->history_pos][i] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tel->cmd_buff[i] = tel->cmd_history[tel->history_pos][i];
|
||||||
|
tel->cmd_pos++;
|
||||||
|
}
|
||||||
|
unsigned char clear_line[] = "\r\033[K";
|
||||||
|
send(tel->sock_client, clear_line, sizeof(clear_line), 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
send(tel->sock_client, tel->cmd_buff, tel->cmd_pos, 0);
|
||||||
|
}
|
||||||
|
else if (tel->history_pos == 0)
|
||||||
|
{
|
||||||
|
tel->history_pos = 255;
|
||||||
|
unsigned char clear_line[] = "\r\033[K";
|
||||||
|
send(tel->sock_client, clear_line, sizeof(clear_line), 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
tel->cmd_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void print_history(telnet_t *tel)
|
||||||
|
{
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
for (int i = 0; i < CMD_HISTERY_NUMBER; i++)
|
||||||
|
{
|
||||||
|
if (tel->cmd_history[i][0] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
send(tel->sock_client, tel->cmd_history[i], strlen(tel->cmd_history[i]), 0);
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void history_save(telnet_t *tel)
|
||||||
|
{
|
||||||
|
// 保存历史命令
|
||||||
|
// tel->history_pos = -1;
|
||||||
|
tel->history_pos = 255;
|
||||||
|
if (tel->history_total < CMD_HISTERY_NUMBER)
|
||||||
|
{
|
||||||
|
tel->history_total++;
|
||||||
|
}
|
||||||
|
// 保存历史记录
|
||||||
|
for (int his = (CMD_HISTERY_NUMBER - 2); his >= 0; his--)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CMD_SIZE; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
tel->cmd_history[his + 1][i] = tel->cmd_history[his][i];
|
||||||
|
if (tel->cmd_history[his][i] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 写入新的历史记录
|
||||||
|
for (int i = 0; i < CMD_SIZE; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
tel->cmd_history[0][i] = tel->cmd_buff[i];
|
||||||
|
if (tel->cmd_buff[i] == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// print_history(tel);
|
||||||
|
}
|
||||||
|
int telnet_config(telnet_t *tel)
|
||||||
|
{
|
||||||
|
if (tel->sock_client < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char cmd[3];
|
||||||
|
// send_dont(cmd, TELOPT_LINEMODE);
|
||||||
|
// send(tel->sock_client,"\033[7e",sizeof("\033[7e"),0);
|
||||||
|
// send_do(cmd, 24);
|
||||||
|
send_will(cmd, TELOPT_ECHO);
|
||||||
|
send_will(cmd, TELOPT_SGA);
|
||||||
|
send_wont(cmd, TELOPT_LINEMODE);
|
||||||
|
// unsigned char line_mode={IAC,SB,TELOPT_LINEMODE,1,0xf,IAC,SE};
|
||||||
|
// send(tel->sock_client,line_mode,sizeof(line_mode),0);
|
||||||
|
// 清理下之前的信息
|
||||||
|
// tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_do(cmd, TELOPT_TTYPE);
|
||||||
|
// 获取下终端类型
|
||||||
|
unsigned char terminal[] = {IAC, SB, TELOPT_TTYPE, 1, IAC, SE};
|
||||||
|
send(tel->sock_client, terminal, sizeof(terminal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int telnet_cmd_handle(telnet_t *tel)
|
||||||
|
{
|
||||||
|
|
||||||
|
extern void key_handle(char *c);
|
||||||
|
|
||||||
|
key_handle(tel->cmd_buff);
|
||||||
|
tel->cmd_pos = 0;
|
||||||
|
}
|
||||||
|
int telnet_shell_handle(telnet_t *tel, char c)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 特殊字符支持
|
||||||
|
*/
|
||||||
|
// 27 91 65 上
|
||||||
|
// 27 91 66 下
|
||||||
|
// 27 91 67 右
|
||||||
|
// 27 91 68 左
|
||||||
|
if (tel->input_mode == 1)
|
||||||
|
{
|
||||||
|
if (c == 91)
|
||||||
|
{
|
||||||
|
tel->input_mode = 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->input_mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tel->input_mode == 2)
|
||||||
|
{
|
||||||
|
if (c == 65)
|
||||||
|
{
|
||||||
|
// 上
|
||||||
|
char cmd[] = {27, 91, 66};
|
||||||
|
// send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->input_mode = 0;
|
||||||
|
histroy_last(tel);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (c == 66)
|
||||||
|
{
|
||||||
|
// 下
|
||||||
|
char cmd[] = {27, 91, 65};
|
||||||
|
// send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->input_mode = 0;
|
||||||
|
histroy_next(tel);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (c == 67)
|
||||||
|
{
|
||||||
|
// 右
|
||||||
|
char cmd[] = {27, 91, 68};
|
||||||
|
// send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->input_mode = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (c == 68)
|
||||||
|
{
|
||||||
|
// 左
|
||||||
|
char cmd[] = {27, 91, 67};
|
||||||
|
// send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->input_mode = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->input_mode = 0;
|
||||||
|
// return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 常规字符支持
|
||||||
|
*/
|
||||||
|
if (c == 13)
|
||||||
|
{
|
||||||
|
tel->cmd_buff[tel->cmd_pos] = '\0';
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
if (tel->table_mode > 0)
|
||||||
|
{
|
||||||
|
// 可能有输出信息,需要清理下
|
||||||
|
unsigned char clear_line[] = "\r\033[K";
|
||||||
|
send(tel->sock_client, clear_line, sizeof(clear_line), 0);
|
||||||
|
tel->table_mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHOW_IN_TELNET();
|
||||||
|
if (tel->cmd_pos > 0)
|
||||||
|
{
|
||||||
|
history_save(tel);
|
||||||
|
}
|
||||||
|
telnet_cmd_handle(tel);
|
||||||
|
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (c == 127 || c == 8)
|
||||||
|
{
|
||||||
|
if (tel->cmd_pos)
|
||||||
|
{
|
||||||
|
tel->cmd_pos--;
|
||||||
|
char cmd[] = {0x08, ' ', 0x08};
|
||||||
|
send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == 0)
|
||||||
|
{
|
||||||
|
// send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else if (c == 10)
|
||||||
|
{
|
||||||
|
// send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else if (c == 27)
|
||||||
|
{
|
||||||
|
tel->input_mode = 1;
|
||||||
|
}
|
||||||
|
else if (c == 9)
|
||||||
|
{
|
||||||
|
if (tel->table_mode < 1)
|
||||||
|
{
|
||||||
|
tel->table_mode++;
|
||||||
|
}
|
||||||
|
extern void shell_auto_completion_for_telnet(void);
|
||||||
|
shell_auto_completion_for_telnet();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tel->cmd_pos < CMD_SIZE)
|
||||||
|
{
|
||||||
|
tel->cmd_buff[tel->cmd_pos++] = c;
|
||||||
|
send(tel->sock_client, &c, 1, 0);
|
||||||
|
// send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send(tel->sock_client, " ", 2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_nor_handle(telnet_t *tel, char c)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (tel->login_in == 0)
|
||||||
|
{
|
||||||
|
if (tel->tel_login_show == 0)
|
||||||
|
{
|
||||||
|
char cmd[] = "\033[?25l";
|
||||||
|
send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->tel_login_show = 1;
|
||||||
|
}
|
||||||
|
// 无论如何回复一个空格
|
||||||
|
send(tel->sock_client, " ", 1, 0);
|
||||||
|
if (tel->passwd[tel->passwd_pos] == c)
|
||||||
|
{
|
||||||
|
tel->passwd_pos++;
|
||||||
|
if (tel->passwd[tel->passwd_pos] == '\0')
|
||||||
|
{
|
||||||
|
tel->login_in = 1;
|
||||||
|
tel->passwd_pos = 0;
|
||||||
|
send(tel->sock_client, "\r\nlogin success\r\n", 17, 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
if (tel->tel_login_show == 1)
|
||||||
|
{
|
||||||
|
char cmd[] = "\033[?25h";
|
||||||
|
send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->tel_login_show = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->passwd_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
telnet_shell_handle(tel, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_rec_handle(telnet_t *tel, unsigned char *c, int len)
|
||||||
|
{
|
||||||
|
#define MOD_NORMAL 0
|
||||||
|
#define MOD_IAC 1
|
||||||
|
#define MOD_WILL 2
|
||||||
|
#define MOD_WONT 3
|
||||||
|
#define MOD_DO 4
|
||||||
|
#define MOD_DONT 5
|
||||||
|
#define MOD_SB 6
|
||||||
|
int state = MOD_NORMAL;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case MOD_NORMAL:
|
||||||
|
if (c[i] == IAC)
|
||||||
|
{
|
||||||
|
state = MOD_IAC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_IAC:
|
||||||
|
if (c[i] == IAC)
|
||||||
|
{
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
// 2个IAC代表字符255,也需要进行处理
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
else if (c[i] == DO)
|
||||||
|
{
|
||||||
|
state = MOD_DO;
|
||||||
|
}
|
||||||
|
else if (c[i] == DONT)
|
||||||
|
{
|
||||||
|
state = MOD_DONT;
|
||||||
|
}
|
||||||
|
else if (c[i] == WILL)
|
||||||
|
{
|
||||||
|
state = MOD_WILL;
|
||||||
|
}
|
||||||
|
else if (c[i] == WONT)
|
||||||
|
{
|
||||||
|
state = MOD_WONT;
|
||||||
|
}
|
||||||
|
else if (c[i] == SB)
|
||||||
|
{
|
||||||
|
state = MOD_SB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WILL:
|
||||||
|
debug_print("telnet: WILL %d\n", c[i]);
|
||||||
|
if (c[i] == TELOPT_NAWS)
|
||||||
|
{
|
||||||
|
if (c[i + 1] == IAC && c[i + 2] == SB && c[i + 3] == TELOPT_NAWS && c[i + 8] == IAC && c[i + 9] == SE)
|
||||||
|
{
|
||||||
|
tel->win_width = ((unsigned short)c[i + 4] << 8) + (unsigned short)c[i + 5];
|
||||||
|
tel->win_height = ((unsigned short)c[i + 6] << 8) + (unsigned short)c[i + 7];
|
||||||
|
i = i + 9;
|
||||||
|
debug_print("telnet: win_width = %d, win_height = %d\n", tel->win_width, tel->win_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_WONT:
|
||||||
|
debug_print("telnet: WONT %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_DO:
|
||||||
|
|
||||||
|
debug_print("telnet: DO %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_DONT:
|
||||||
|
|
||||||
|
debug_print("telnet: DONT %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_SB:
|
||||||
|
if (c[i] == TELOPT_TTYPE && c[i + 1] == 0)
|
||||||
|
{
|
||||||
|
i = i + 2;
|
||||||
|
int k = 0;
|
||||||
|
// 客户端类型
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((c[i] == IAC && c[i + 1] == SE) || i == len)
|
||||||
|
{
|
||||||
|
tel->cilent_type_name[k] = '\0';
|
||||||
|
printf("telnet: client type = %s\n", tel->cilent_type_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tel->cilent_type_name[k] = c[i];
|
||||||
|
i++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_core(telnet_t *tel)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (tel->init == 0)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
debug_print("\ntelnet: waiting for connection\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int addr_len = sizeof(tel->client_addr);
|
||||||
|
tel->sock_client = accept(tel->sock_server, (void *)&tel->client_addr, &addr_len);
|
||||||
|
if (tel->sock_client < 0)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_print("telnet: new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(tel->client_addr.sin_addr), tel->client_addr.sin_port);
|
||||||
|
int ret = telnet_config(tel);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: client disconnected\n");
|
||||||
|
close(tel->sock_client);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tel->login_in == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
send(tel->sock_client, "admin login: \r\n", 15, 0);
|
||||||
|
}
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// telnet_host_function();
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
// if (tel->rec_buff[0] == IAC && tel->rec_buff[1] != IAC)
|
||||||
|
// {
|
||||||
|
// telnet_config_back(tel);
|
||||||
|
// }
|
||||||
|
if (tel->rec_len > 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: recv_len = %d\n", tel->rec_len);
|
||||||
|
for (int i = 0; i < tel->rec_len; i++)
|
||||||
|
{
|
||||||
|
switch (tel->rec_buff[i])
|
||||||
|
{
|
||||||
|
case IAC:
|
||||||
|
debug_print("IAC,");
|
||||||
|
break;
|
||||||
|
case DO:
|
||||||
|
debug_print("DO,");
|
||||||
|
break;
|
||||||
|
case DONT:
|
||||||
|
debug_print("DONT,");
|
||||||
|
break;
|
||||||
|
case WILL:
|
||||||
|
debug_print("WILL,");
|
||||||
|
break;
|
||||||
|
case WONT:
|
||||||
|
debug_print("WONT,");
|
||||||
|
break;
|
||||||
|
case SB:
|
||||||
|
debug_print("SB,");
|
||||||
|
break;
|
||||||
|
case SE:
|
||||||
|
debug_print("SE,");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug_print("%d,", tel->rec_buff[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_print("\n");
|
||||||
|
telnet_rec_handle(tel, tel->rec_buff, tel->rec_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug_print("telnet: client disconnected\n");
|
||||||
|
tel->login_in = 0;
|
||||||
|
// tel->history_total=0;
|
||||||
|
// for (int i = 0; i < CMD_HISTERY_NUMBER; i++)
|
||||||
|
// {
|
||||||
|
// for (int j = 0; j < CMD_SIZE; j++)
|
||||||
|
// {
|
||||||
|
// tel->cmd_history[i][j] = '\0';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
close(tel->sock_client);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void telnet_put_char(char c)
|
||||||
|
{
|
||||||
|
if (telnet.login_in == 1 && telnet.init == 1)
|
||||||
|
{
|
||||||
|
send(telnet.sock_client, &c, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void telnet_send_string(char *c, int len)
|
||||||
|
{
|
||||||
|
if (telnet.login_in == 1 && telnet.init == 1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
// 转移字符处理
|
||||||
|
if (c[i] == IAC)
|
||||||
|
{
|
||||||
|
send(telnet.sock_client, &c[i], 1, 0);
|
||||||
|
}
|
||||||
|
if (c[i] == '\n')
|
||||||
|
{
|
||||||
|
char temp = '\r';
|
||||||
|
send(telnet.sock_client, &temp, 1, 0);
|
||||||
|
}
|
||||||
|
send(telnet.sock_client, &c[i], 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void *telnet_thread_handle(void *args)
|
||||||
|
{
|
||||||
|
telnet_init(&telnet, TELNET_PORT);
|
||||||
|
telnet_core(&telnet);
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: 陈逸凡 1343619937@qq.com
|
||||||
|
# @Date: 2024-04-11 13:50:57
|
||||||
|
# @LastEditors: 陈逸凡 1343619937@qq.com
|
||||||
|
# @LastEditTime: 2024-04-18 11:36:08
|
||||||
|
# @FilePath: \telnet\start.sh
|
||||||
|
# @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
###
|
||||||
|
gcc telnet_server.c -o telnet_server
|
||||||
|
sudo ./telnet_server
|
|
@ -0,0 +1,344 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1983, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)telnet.h 8.2 (Berkeley) 12/15/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TELNET_H_
|
||||||
|
#define _TELNET_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for the TELNET protocol.
|
||||||
|
*/
|
||||||
|
#define IAC 255 /* interpret as command: */
|
||||||
|
#define DONT 254 /* you are not to use option */
|
||||||
|
#define DO 253 /* please, you use option */
|
||||||
|
#define WONT 252 /* I won't use option */
|
||||||
|
#define WILL 251 /* I will use option */
|
||||||
|
#define SB 250 /* interpret as subnegotiation */
|
||||||
|
#define GA 249 /* you may reverse the line */
|
||||||
|
#define EL 248 /* erase the current line */
|
||||||
|
#define EC 247 /* erase the current character */
|
||||||
|
#define AYT 246 /* are you there */
|
||||||
|
#define AO 245 /* abort output--but let prog finish */
|
||||||
|
#define IP 244 /* interrupt process--permanently */
|
||||||
|
#define BREAK 243 /* break */
|
||||||
|
#define DM 242 /* data mark--for connect. cleaning */
|
||||||
|
#define NOP 241 /* nop */
|
||||||
|
#define SE 240 /* end sub negotiation */
|
||||||
|
#define EOR 239 /* end of record (transparent mode) */
|
||||||
|
#define ABORT 238 /* Abort process */
|
||||||
|
#define SUSP 237 /* Suspend process */
|
||||||
|
#define xEOF 236 /* End of file: EOF is already used... */
|
||||||
|
|
||||||
|
#define SYNCH 242 /* for telfunc calls */
|
||||||
|
|
||||||
|
#ifdef TELCMDS
|
||||||
|
char *telcmds[] = {
|
||||||
|
"EOF", "SUSP", "ABORT", "EOR",
|
||||||
|
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
|
||||||
|
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *telcmds[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TELCMD_FIRST xEOF
|
||||||
|
#define TELCMD_LAST IAC
|
||||||
|
#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
|
||||||
|
(unsigned int)(x) >= TELCMD_FIRST)
|
||||||
|
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
|
||||||
|
|
||||||
|
/* telnet options */
|
||||||
|
#define TELOPT_BINARY 0 /* 8-bit data path */
|
||||||
|
#define TELOPT_ECHO 1 /* echo */
|
||||||
|
#define TELOPT_RCP 2 /* prepare to reconnect */
|
||||||
|
#define TELOPT_SGA 3 /* suppress go ahead */
|
||||||
|
#define TELOPT_NAMS 4 /* approximate message size */
|
||||||
|
#define TELOPT_STATUS 5 /* give status */
|
||||||
|
#define TELOPT_TM 6 /* timing mark */
|
||||||
|
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
|
||||||
|
#define TELOPT_NAOL 8 /* negotiate about output line width */
|
||||||
|
#define TELOPT_NAOP 9 /* negotiate about output page size */
|
||||||
|
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
|
||||||
|
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
|
||||||
|
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
|
||||||
|
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
|
||||||
|
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
|
||||||
|
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
|
||||||
|
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
|
||||||
|
#define TELOPT_XASCII 17 /* extended ascic character set */
|
||||||
|
#define TELOPT_LOGOUT 18 /* force logout */
|
||||||
|
#define TELOPT_BM 19 /* byte macro */
|
||||||
|
#define TELOPT_DET 20 /* data entry terminal */
|
||||||
|
#define TELOPT_SUPDUP 21 /* supdup protocol */
|
||||||
|
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
|
||||||
|
#define TELOPT_SNDLOC 23 /* send location */
|
||||||
|
#define TELOPT_TTYPE 24 /* terminal type */
|
||||||
|
#define TELOPT_EOR 25 /* end or record */
|
||||||
|
#define TELOPT_TUID 26 /* TACACS user identification */
|
||||||
|
#define TELOPT_OUTMRK 27 /* output marking */
|
||||||
|
#define TELOPT_TTYLOC 28 /* terminal location number */
|
||||||
|
#define TELOPT_3270REGIME 29 /* 3270 regime */
|
||||||
|
#define TELOPT_X3PAD 30 /* X.3 PAD */
|
||||||
|
#define TELOPT_NAWS 31 /* window size */
|
||||||
|
#define TELOPT_TSPEED 32 /* terminal speed */
|
||||||
|
#define TELOPT_LFLOW 33 /* remote flow control */
|
||||||
|
#define TELOPT_LINEMODE 34 /* Linemode option */
|
||||||
|
#define TELOPT_XDISPLOC 35 /* X Display Location */
|
||||||
|
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
|
||||||
|
#define TELOPT_AUTHENTICATION 37/* Authenticate */
|
||||||
|
#define TELOPT_ENCRYPT 38 /* Encryption option */
|
||||||
|
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
|
||||||
|
#define TELOPT_EXOPL 255 /* extended-options-list */
|
||||||
|
|
||||||
|
// #define TELOPTS
|
||||||
|
#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
|
||||||
|
#ifdef TELOPTS
|
||||||
|
char *telopts[NTELOPTS+1] = {
|
||||||
|
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
|
||||||
|
"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
|
||||||
|
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
|
||||||
|
"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
|
||||||
|
"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
|
||||||
|
"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
|
||||||
|
"TACACS UID", "OUTPUT MARKING", "TTYLOC",
|
||||||
|
"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
|
||||||
|
"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
|
||||||
|
"ENCRYPT", "NEW-ENVIRON",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
#define TELOPT_FIRST TELOPT_BINARY
|
||||||
|
#define TELOPT_LAST TELOPT_NEW_ENVIRON
|
||||||
|
#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
|
||||||
|
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sub-option qualifiers */
|
||||||
|
#define TELQUAL_IS 0 /* option is... */
|
||||||
|
#define TELQUAL_SEND 1 /* send option */
|
||||||
|
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
|
||||||
|
#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
|
||||||
|
#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
|
||||||
|
|
||||||
|
#define LFLOW_OFF 0 /* Disable remote flow control */
|
||||||
|
#define LFLOW_ON 1 /* Enable remote flow control */
|
||||||
|
#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
|
||||||
|
#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LINEMODE suboptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LM_MODE 1
|
||||||
|
#define LM_FORWARDMASK 2
|
||||||
|
#define LM_SLC 3
|
||||||
|
|
||||||
|
#define MODE_EDIT 0x01
|
||||||
|
#define MODE_TRAPSIG 0x02
|
||||||
|
#define MODE_ACK 0x04
|
||||||
|
#define MODE_SOFT_TAB 0x08
|
||||||
|
#define MODE_LIT_ECHO 0x10
|
||||||
|
|
||||||
|
#define MODE_MASK 0x1f
|
||||||
|
|
||||||
|
/* Not part of protocol, but needed to simplify things... */
|
||||||
|
#define MODE_FLOW 0x0100
|
||||||
|
#define MODE_ECHO 0x0200
|
||||||
|
#define MODE_INBIN 0x0400
|
||||||
|
#define MODE_OUTBIN 0x0800
|
||||||
|
#define MODE_FORCE 0x1000
|
||||||
|
|
||||||
|
#define SLC_SYNCH 1
|
||||||
|
#define SLC_BRK 2
|
||||||
|
#define SLC_IP 3
|
||||||
|
#define SLC_AO 4
|
||||||
|
#define SLC_AYT 5
|
||||||
|
#define SLC_EOR 6
|
||||||
|
#define SLC_ABORT 7
|
||||||
|
#define SLC_EOF 8
|
||||||
|
#define SLC_SUSP 9
|
||||||
|
#define SLC_EC 10
|
||||||
|
#define SLC_EL 11
|
||||||
|
#define SLC_EW 12
|
||||||
|
#define SLC_RP 13
|
||||||
|
#define SLC_LNEXT 14
|
||||||
|
#define SLC_XON 15
|
||||||
|
#define SLC_XOFF 16
|
||||||
|
#define SLC_FORW1 17
|
||||||
|
#define SLC_FORW2 18
|
||||||
|
|
||||||
|
#define NSLC 18
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For backwards compatability, we define SLC_NAMES to be the
|
||||||
|
* list of names if SLC_NAMES is not defined.
|
||||||
|
*/
|
||||||
|
#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
|
||||||
|
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
|
||||||
|
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
|
||||||
|
#ifdef SLC_NAMES
|
||||||
|
char *slc_names[] = {
|
||||||
|
SLC_NAMELIST
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *slc_names[];
|
||||||
|
#define SLC_NAMES SLC_NAMELIST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
|
||||||
|
#define SLC_NAME(x) slc_names[x]
|
||||||
|
|
||||||
|
#define SLC_NOSUPPORT 0
|
||||||
|
#define SLC_CANTCHANGE 1
|
||||||
|
#define SLC_VARIABLE 2
|
||||||
|
#define SLC_DEFAULT 3
|
||||||
|
#define SLC_LEVELBITS 0x03
|
||||||
|
|
||||||
|
#define SLC_FUNC 0
|
||||||
|
#define SLC_FLAGS 1
|
||||||
|
#define SLC_VALUE 2
|
||||||
|
|
||||||
|
#define SLC_ACK 0x80
|
||||||
|
#define SLC_FLUSHIN 0x40
|
||||||
|
#define SLC_FLUSHOUT 0x20
|
||||||
|
|
||||||
|
#define OLD_ENV_VAR 1
|
||||||
|
#define OLD_ENV_VALUE 0
|
||||||
|
#define NEW_ENV_VAR 0
|
||||||
|
#define NEW_ENV_VALUE 1
|
||||||
|
#define ENV_ESC 2
|
||||||
|
#define ENV_USERVAR 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AUTHENTICATION suboptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Who is authenticating who ...
|
||||||
|
*/
|
||||||
|
#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
|
||||||
|
#define AUTH_WHO_SERVER 1 /* Server authenticating client */
|
||||||
|
#define AUTH_WHO_MASK 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* amount of authentication done
|
||||||
|
*/
|
||||||
|
#define AUTH_HOW_ONE_WAY 0
|
||||||
|
#define AUTH_HOW_MUTUAL 2
|
||||||
|
#define AUTH_HOW_MASK 2
|
||||||
|
|
||||||
|
#define AUTHTYPE_NULL 0
|
||||||
|
#define AUTHTYPE_KERBEROS_V4 1
|
||||||
|
#define AUTHTYPE_KERBEROS_V5 2
|
||||||
|
#define AUTHTYPE_SPX 3
|
||||||
|
#define AUTHTYPE_MINK 4
|
||||||
|
#define AUTHTYPE_CNT 5
|
||||||
|
|
||||||
|
#define AUTHTYPE_TEST 99
|
||||||
|
|
||||||
|
#ifdef AUTH_NAMES
|
||||||
|
char *authtype_names[] = {
|
||||||
|
"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *authtype_names[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
|
||||||
|
#define AUTHTYPE_NAME(x) authtype_names[x]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ENCRYPTion suboptions
|
||||||
|
*/
|
||||||
|
#define ENCRYPT_IS 0 /* I pick encryption type ... */
|
||||||
|
#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
|
||||||
|
#define ENCRYPT_REPLY 2 /* Initial setup response */
|
||||||
|
#define ENCRYPT_START 3 /* Am starting to send encrypted */
|
||||||
|
#define ENCRYPT_END 4 /* Am ending encrypted */
|
||||||
|
#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
|
||||||
|
#define ENCRYPT_REQEND 6 /* Request you send encrypting */
|
||||||
|
#define ENCRYPT_ENC_KEYID 7
|
||||||
|
#define ENCRYPT_DEC_KEYID 8
|
||||||
|
#define ENCRYPT_CNT 9
|
||||||
|
|
||||||
|
#define ENCTYPE_ANY 0
|
||||||
|
#define ENCTYPE_DES_CFB64 1
|
||||||
|
#define ENCTYPE_DES_OFB64 2
|
||||||
|
#define ENCTYPE_CNT 3
|
||||||
|
|
||||||
|
#ifdef ENCRYPT_NAMES
|
||||||
|
char *encrypt_names[] = {
|
||||||
|
"IS", "SUPPORT", "REPLY", "START", "END",
|
||||||
|
"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
char *enctype_names[] = {
|
||||||
|
"ANY", "DES_CFB64", "DES_OFB64", 0,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
extern char *encrypt_names[];
|
||||||
|
extern char *enctype_names[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
|
||||||
|
#define ENCRYPT_NAME(x) encrypt_names[x]
|
||||||
|
|
||||||
|
#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
|
||||||
|
#define ENCTYPE_NAME(x) enctype_names[x]
|
||||||
|
|
||||||
|
#endif /* !_TELNET_H_ */
|
|
@ -0,0 +1,493 @@
|
||||||
|
# 概览
|
||||||
|
|
||||||
|
Telnet("teletype network"的缩写)是一种客户端/服务器应用协议,它提供对局域网或互联网上远程系统的虚拟终端的访问。它是一种双向8位通信的协议。其主要目标是连接终端设备和面向终端的进程。
|
||||||
|
|
||||||
|
Telnet 由两个组成部分构成:(1)协议本身,它规定了两个方如何通信;(2)提供服务的软件应用程序。用户数据与 Telnet 控制信息一起,以 8 位字节为基础的数据连接通过传输控制协议(TCP)进行交错传输。Telnet 于 1969 年开发,起始于 RFC 15,后在 RFC 855 中得到扩展,并被标准化为互联网工程任务组(IETF)互联网标准 STD 8,这是最早的互联网标准之一。Telnet 传输的所有信息,包括用户名和密码,都是以明文形式,因此不推荐用于对安全性要求较高的应用,如远程管理路由器。使用 Telnet 进行此类操作的情况已大幅减少,转而更多采用 SSH。已经提出了一些为 Telnet 提供加密的扩展。
|
||||||
|
|
||||||
|
# 组成
|
||||||
|
|
||||||
|
Telnet 由两部分组成:(1)协议本身和(2)服务组件。Telnet 协议是基于可靠的面向连接的传输的客户端-服务器协议。该协议用于建立连接到传输控制协议(TCP)端口号23或2323,这是 Telnet 服务器应用程序正在监听的位置。Telnet 协议将任何终端抽象为一个网络虚拟终端(NVT)。客户端在与服务器通信时必须使用 NVT 代码来模拟一个网络虚拟终端。
|
||||||
|
|
||||||
|
Telnet 在 UDP/IP 之前已经存在,最初是在网络控制协议(NCP)之上运行。Telnet 服务最好在以下情境中理解:一个用户使用简单的终端,通过本地的 Telnet 程序(即客户端程序)在远程计算机上运行登录会话,用户的通信需求由 Telnet 服务器程序处理。
|
||||||
|
|
||||||
|
# 协议
|
||||||
|
|
||||||
|
## 历史
|
||||||
|
|
||||||
|
虽然Telnet最初是一个临时的协议,直到1973年3月5日才有正式的定义,但其名称实际上指的是“网络上的电传打字机协议”(Teletype Over Network Protocol)。RFC 206(NIC 7176)中对Telnet的描述明确了这一点:
|
||||||
|
|
||||||
|
TELNET协议基于虚拟电传打字机的概念,使用7位ASCII字符集。因此,用户TELNET的主要功能是提供一种手段,使其用户可以“敲击”那个虚拟电传打字机上的所有键。
|
||||||
|
|
||||||
|
本质上,它使用8位通道来交换7位ASCII数据。任何高位被设置的字节都是特殊的Telnet字符。1973年3月5日,在加州大学洛杉矶分校(UCLA)定义了Telnet协议标准,同时发布了两个NIC文件:《Telnet协议规范》(NIC 15372)和《Telnet选项规范》(NIC 15373)。这些文件为Telnet的发展提供了官方标准和详细的操作规范。
|
||||||
|
|
||||||
|
## 选项
|
||||||
|
|
||||||
|
Telnet的协议架构允许进行可协商的选项,因此许多扩展被引入。其中一些扩展已被采纳为互联网标准,即IETF文件中的STD 27至STD 32。这些标准包括不同的Telnet选项,如二进制传输、回显、抑制去向和终端类型协商等。
|
||||||
|
|
||||||
|
这些扩展有些已被广泛实施,而其他一些则是IETF标准轨道上的建议标准。例如,有些扩展提供了改进的安全性或兼容性特性,使Telnet能够在更多的环境中使用,尽管在安全性要求高的应用中,人们通常会选择使用更安全的协议,如SSH。
|
||||||
|
|
||||||
|
以下是一些IETF标准轨道上的Telnet扩展示例:
|
||||||
|
|
||||||
|
1. **Telnet二进制传输**(Telnet Binary Transmission):允许数据以二进制形式传输,而不仅限于7位ASCII。
|
||||||
|
2. **Telnet回显选项**(Telnet Echo Option):允许服务器控制回显功能,这对于实现远程命令行界面非常有用。
|
||||||
|
3. **Telnet抑制去向协商**(Suppress Go Ahead):在双向操作模式中,删除了不必要的网络流量,优化了通信效率。
|
||||||
|
4. **Telnet终端类型**(Terminal Type):允许客户端和服务器协商终端类型,使服务器可以根据连接的终端类型提供适当的输出。
|
||||||
|
|
||||||
|
这些扩展和其他相关的改进使Telnet能够在其生命周期内适应网络环境的变化,尽管如今它已经大部分被更现代的技术所取代。
|
||||||
|
|
||||||
|
## 服务
|
||||||
|
|
||||||
|
Telnet服务是通过Telnet协议提供服务的应用程序。大多数操作系统提供了一项服务,可以安装或启用以向客户端提供Telnet服务。
|
||||||
|
|
||||||
|
# 安全漏洞
|
||||||
|
|
||||||
|
Telnet容易受到网络攻击的威胁,如嗅探数据包以窃取敏感信息,包括密码和指纹信息。Telnet服务还容易受到利用,通过嗅探横幅泄露服务器信息(如主机名、IP地址和品牌),进而搜索确定Telnet服务是否接受未经身份验证的连接。Telnet也经常被恶意软件利用,因为它配置不当。事实上,与其他常见协议相比,Telnet更常被攻击者针对,尤其是与UPnP、CoAP、MQTT、AMQP和XMPP相比。常被攻击的设备包括物联网设备、路由器和调制解调器。
|
||||||
|
|
||||||
|
SANS Institute建议,在正常情况下应停止使用Telnet进行远程登录,原因如下:
|
||||||
|
|
||||||
|
1. 默认情况下,Telnet不加密连接上发送的任何数据(包括密码),因此往往可以窃听通信,并稍后将密码用于恶意目的。
|
||||||
|
2. 大多数Telnet实现缺乏身份验证。安全研究人员发现的约22,887个Telnet启用设备不仅缺乏身份验证,而且还提供对系统的无限制访问。
|
||||||
|
3. 大多数Telnet身份验证机制容易受到中间人攻击的拦截。
|
||||||
|
|
||||||
|
Telnet的扩展提供了传输层安全性(TLS)和简单认证与安全层(SASL)身份验证,以解决上述问题。然而,大多数Telnet实现不支持这些扩展;而且它们也无法解决其他漏洞,如解析横幅信息。
|
||||||
|
|
||||||
|
通过自定义Telnet客户端(TN5250/TN3270)和IBM i系统,支持IBM 5250或3270工作站仿真。设计用于通过Telnet传递IBM 5250数据流的客户端和服务器通常支持SSL加密,因为SSH不包括5250仿真。在IBM i(也称为OS/400)下,端口992是安全Telnet的默认端口。
|
||||||
|
|
||||||
|
## 历史使用方式
|
||||||
|
|
||||||
|
Telnet 提供了对远程主机上命令行界面的访问。然而,由于通过开放网络(如互联网)使用 Telnet 存在严重的安全问题,其用途已大大减少,转而支持 SSH(Secure Shell)。SSH 提供了 Telnet 的许多功能,增加了强加密功能,以防止密码等敏感数据被截获,以及公钥身份验证,以确保远程计算机确实是其所声称的那个。
|
||||||
|
|
||||||
|
随着时间的推移,特别是在公共互联网上,使用 Telnet 进行远程管理的频率已经迅速下降,转而使用更安全的 SSH 协议。这种变化主要是由于:
|
||||||
|
|
||||||
|
1. 安全性:SSH 通过加密所有传输的数据,提供了比 Telnet 更高的安全级别。这保护了传输中的数据不被窃听或篡改。
|
||||||
|
2. 认证强度:SSH 支持更先进的认证机制,如公钥/私钥对,而不仅仅是密码。这减少了身份验证数据被盗用或破解的风险。
|
||||||
|
3. 功能性:SSH 不仅支持远程命令行访问,还支持端口转发、文件传输等高级功能。
|
||||||
|
|
||||||
|
因此,尽管 Telnet 曾广泛用于教育和研究环境中进行远程管理和网络测试,现在它的使用主要限于内部网络或那些不需要高安全性的特定环境。在绝大多数现代网络环境中,SSH 由于其增强的安全性和功能性,已成为远程访问的首选协议。
|
||||||
|
|
||||||
|
## 现在的使用方式
|
||||||
|
|
||||||
|
Telnet客户端可用于调试诸如SMTP、IRC、HTTP、FTP或POP3等网络服务,以向服务器发出命令并检查响应。例如,Telnet客户端应用程序可以建立与Telnet服务器端口之外的端口的交互式TCP会话。然而,与这些端口的通信不涉及Telnet协议,因为这些服务仅使用透明的8位TCP连接,因为Telnet协议的大多数元素都是围绕着访问命令行界面的想法设计的,而这些选项或机制在大多数其他Internet服务连接中都没有使用。
|
||||||
|
|
||||||
|
例如,命令行Telnet客户端可以如下向TCP端口80上的Web服务器发出HTTP请求:
|
||||||
|
|
||||||
|
如今,这种较老的协议只在极少数情况下用于访问几十年前的遗留设备,因为这些设备不支持更现代的协议。例如,许多工业和科学设备只有Telnet作为通信选项。有些设备仅带有标准的RS-232端口,并使用串行服务器硬件设备来提供TCP/Telnet数据和RS-232串行数据之间的转换。在这种情况下,SSH并不是一个选择,除非可以为接口设备配置SSH(或者用支持SSH的设备替换)。
|
||||||
|
|
||||||
|
业余无线电操作员通常使用Telnet提供公共信息。
|
||||||
|
|
||||||
|
尽管不建议使用Telnet,但安全研究人员估计截至2021年,仍有7,096,465个Internet上的系统暴露使用Telnet。然而,关于这个数字的估计因超出默认TCP端口23的端口扫描数量而有很大不同。
|
||||||
|
|
||||||
|
# 协议内容
|
||||||
|
|
||||||
|
## 常用的ASCII码:
|
||||||
|
|
||||||
|
- NULL(空字符):字节码为0。在文本中通常表示字符串的结束或空字符。
|
||||||
|
- Line feed(换行):字节码为10。在Unix和Unix-like系统中表示换行。
|
||||||
|
- Carriage return(回车):字节码为13。在老式的打字机中表示将打印头移回行首。
|
||||||
|
- Bell(响铃):字节码为7。在打印机或终端上发出声音或闪烁光标,用于提醒用户。
|
||||||
|
- Backspace(退格):字节码为8。在文本编辑中表示向左移动光标一个位置,通常用于删除最后输入的字符。
|
||||||
|
- Horizontal tab(水平制表符):字节码为9。在文本编辑中表示向右移动光标到下一个制表位。
|
||||||
|
- Vertical tab(垂直制表符):字节码为11。在文本中很少使用,可以用于在打印机上控制页面的垂直间距。
|
||||||
|
- Form feed(换页):字节码为12。在打印机中表示换页,将打印位置移动到下一页。
|
||||||
|
|
||||||
|
这些控制码可以在文本编辑、打印和终端控制等场景中使用,用于控制文本的格式和行为。
|
||||||
|
|
||||||
|
## telnet命令
|
||||||
|
|
||||||
|
Telnet命令至少由两个字节组成。第一个字节是IAC转义字符(通常为字节255),后跟给定命令的字节码:
|
||||||
|
|
||||||
|
| 功能 | 字节码 | 说明 |
|
||||||
|
| ----------------------------- | ------ | ---------------------------------------- |
|
||||||
|
| SE(子协商结束) | 240 | 结束协商(或数据块)的子服务的协议机制。 |
|
||||||
|
| NOP(无操作) | 241 | 不执行任何操作的数据包。 |
|
||||||
|
| Data Mark(数据标记) | 242 | |
|
||||||
|
| Break(中断) | 243 | |
|
||||||
|
| Interrupt Process(中断进程) | 244 | 请求另一方结束当前进程。 |
|
||||||
|
| Abort output(中止输出) | 245 | 请求另一方停止发送输出。 |
|
||||||
|
| Are you there?(你在吗?) | 246 | |
|
||||||
|
| Erase character(擦除字符) | 247 | |
|
||||||
|
| Erase Line(擦除行) | 248 | |
|
||||||
|
| Go ahead(继续) | 249 | |
|
||||||
|
| SB(子协商开始) | 250 | 启动协议机制的子服务的协商。 |
|
||||||
|
| WILL | 251 | 通知另一方,本方将使用某个协议机制。 |
|
||||||
|
| WON'T | 252 | 通知另一方,本方将不使用某个协议机制。 |
|
||||||
|
| DO | 253 | 指示另一方使用某个协议机制。 |
|
||||||
|
| DON'T | 254 | 指示另一方不要使用某个协议机制。 |
|
||||||
|
| IAC(序列初始化器/转义字符) | 255 | |
|
||||||
|
|
||||||
|
希望这个表格能够帮助你更清晰地理解这些功能和它们的字节码。
|
||||||
|
|
||||||
|
这些命令用于Telnet协议的控制和协商,以便在Telnet会话期间执行各种操作和协议交互。
|
||||||
|
|
||||||
|
## telnet转移字符
|
||||||
|
|
||||||
|
除了0xff之外的所有数据八位组都按原样传输到Telnet上。(0xff,或十进制255,是IAC字节(Interpret As Command),它表示下一个字节是Telnet命令。插入0xff到流中的命令是0xff,所以当通过Telnet协议发送数据时,必须将0xff转义为两倍。)
|
||||||
|
|
||||||
|
好的,下面是将上述内容转换为表格并翻译成中文的结果:
|
||||||
|
|
||||||
|
| 代码 | 名称 | 规范 | 备注 |
|
||||||
|
| ------- | ------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| 0 | 二进制传输 | RFC 856 | 8位模式(即二进制选项)旨在传输二进制数据,而不是ASCII字符。标准建议将代码0000–0176解释为ASCII,但并未提供高位设置数据八位组的任何含义。曾尝试引入类似于HTTP的可切换字符编码支持,但对其实际软件支持情况一无所知。 |
|
||||||
|
| 1 | 回显 | RFC 857 | |
|
||||||
|
| 2 | 重新连接 | 1973年NIC 15391 | |
|
||||||
|
| 3 | 抑制前导 | RFC 858 | 原始Telnet协议中的“Go Ahead”命令代码(249)用于通知另一端,另一端可以开始发送消息。这在“半双工”通信中使用,因为某些终端可以发送消息和接收消息,但不能同时进行。 |
|
||||||
|
| 4 | 大小约定 | 1973年NIC 15393 | |
|
||||||
|
| 5 | 状态 | RFC 859 | |
|
||||||
|
| 6 | 时间标记 | RFC 860 | |
|
||||||
|
| 7 | 远程控制传输和回显 | RFC 726 | |
|
||||||
|
| 8 | 输出行宽 | 1978年8月NIC 20196 | |
|
||||||
|
| 9 | 输出页大小 | 1978年8月NIC 20197 | |
|
||||||
|
| 10 | 输出回车符处理 | RFC 652 | |
|
||||||
|
| 11 | 输出水平制表符站位 | RFC 653 | |
|
||||||
|
| 12 | 输出水平制表符处理 | RFC 654 | |
|
||||||
|
| 13 | 输出换页符处理 | RFC 655 | |
|
||||||
|
| 14 | 输出垂直制表符站位 | RFC 656 | |
|
||||||
|
| 15 | 输出垂直制表符处理 | RFC 657 | |
|
||||||
|
| 16 | 输出换行符处理 | RFC 658 | |
|
||||||
|
| 17 | 扩展ASCII | RFC 698 | |
|
||||||
|
| 18 | 注销 | RFC 727 | |
|
||||||
|
| 19 | 字节宏 | RFC 735 | |
|
||||||
|
| 20 | 数据输入终端 | RFC 1043, RFC 732 | |
|
||||||
|
| 21 | SUPDUP | RFC 736, RFC 734 | |
|
||||||
|
| 22 | SUPDUP输出 | RFC 749 | |
|
||||||
|
| 23 | 发送位置 | RFC 779 | |
|
||||||
|
| 24 | 终端类型 | RFC 1091 | |
|
||||||
|
| 25 | 记录结束 | RFC 885 | |
|
||||||
|
| 26 | TACACS用户识别 | RFC 927 | |
|
||||||
|
| 27 | 输出标记 | RFC 933 | |
|
||||||
|
| 28 | 终端位置号 | RFC 946 | |
|
||||||
|
| 29 | Telnet 3270模式 | RFC 1041 | |
|
||||||
|
| 30 | X.3 PAD | RFC 1053 | |
|
||||||
|
| 31 | 关于窗口大小协商 | RFC 1073 | |
|
||||||
|
| 32 | 终端速度 | RFC 1079 | |
|
||||||
|
| 33 | 远程流量控制 | RFC 1372 | |
|
||||||
|
| 34 | Linemode | RFC 1184 | |
|
||||||
|
| 35 | X显示位置 | RFC 1096 | |
|
||||||
|
| 36 | 环境选项 | RFC 1408 | |
|
||||||
|
| 37 | 认证选项 | RFC 2941 | |
|
||||||
|
| 38 | 加密选项 | RFC 2946 | |
|
||||||
|
| 39 | 新环境选项 | RFC 1572 | |
|
||||||
|
| 40 | TN3270E | RFC 2355 | |
|
||||||
|
| 41 | XAUTH | | |
|
||||||
|
| 42 | 字符集 | RFC 2066 | |
|
||||||
|
| 43 | Telnet远程串行端口(RSP) | | |
|
||||||
|
| 44 | COM端口控制选项 | RFC 2217 | |
|
||||||
|
| 45 | Telnet抑制本地回显 | | |
|
||||||
|
| 46 | Telnet启动TLS | | |
|
||||||
|
| 47 | KERMIT | RFC 2840 | |
|
||||||
|
| 48 | 发送URL | | |
|
||||||
|
| 49 | FORWARD_X | | |
|
||||||
|
| 50-137 | 未分配 | | |
|
||||||
|
| 138 | TELOPT PRAGMA LOGON | | |
|
||||||
|
| 139 | TELOPT SSPI LOGON | | |
|
||||||
|
| 140 | TELOPT PRAGMA HEARTBEAT | | |
|
||||||
|
| 141-254 | 未分配 | | |
|
||||||
|
| 255 | 扩展选项列表 | RFC 861 | |
|
||||||
|
|
||||||
|
# RFC 854
|
||||||
|
|
||||||
|
## 1. 介绍
|
||||||
|
|
||||||
|
TELNET的目标是提供一个相对通用,双向,面向八位字节的通信机制。它的主要目的标是允许通过标准方法来连接终端设备和面向各个终端的进程。可以想象此协议同样可用于终端间通信(“链接”)以及进程间通信(“分布式计算”)。
|
||||||
|
|
||||||
|
## 2. 总则
|
||||||
|
|
||||||
|
TELNET连接是用于传输带有TELNET控制信息的数据的TCP连接。
|
||||||
|
|
||||||
|
TELNET协议的设计主要基于三点:一、网络虚拟终端(Network Virtual Terminal)的概念;二、选项可协商的原理;三、平等看待终端和进程。
|
||||||
|
|
||||||
|
1.一个Telnet连接建立时,两端都做为一个“网络虚拟终端(NVT)”来发起来关闭。一个NVT是一个提供标准的、网络范围的、中间的规范终端的代表。这使得“服务器”和“用户”无需保存对方终端和终端处理协定的相关信息。所有的主机,包括用户和服务器,把他们本地的设备属性和协定映射为一个网络上的NVT,同时可以假设对方也有一个类似的映射。NVT试图在过度约束(没有提供给主机足够的词汇来映射到他们的本地字符集)和过度包容(限定用户使用适当的终端)之间取得平衡。
|
||||||
|
|
||||||
|
注意:“用户”端指那些通常带有物理终端的主机,“服务器”指的是那些能够提供一些服务的机器。另一个类似的观点(同样适用于端对端和过程对过程通信环境)是,“用户”指的是初始化通信连接的机器。
|
||||||
|
|
||||||
|
2.可选项协商的原理基于这样一个事实:许多主机都希望能够在NVT之上提供更多的服务,许多用户将会拥有一个更复杂的终端,并且希望能够得到一流的,而不是极少的一点服务。尽管相互独立,但TELNET协议中内建有许多的“选项”,这些被认可的选项与“DO,DON'T,WILL,WON'T”结构一起使用以允许用户和服务器协商在他们的TELNET连接上使用更复杂的(或者差异的)约定。这些选项包括改变字符集,回显模式等。
|
||||||
|
|
||||||
|
设置选项使用的基本策略,是让每一方(或双方)初始化一个使一些选项有效的请求,另一方可以接受或拒绝该请求。如果该请求被接受了,选项立即生效;如果该请求被拒绝,相关特性将保持与NVT默认的一致。很显然,一方可以总是拒绝启用某个选项的请求,但不应拒绝任何禁用某个选项的请求,因为双方都应支持NVT。
|
||||||
|
|
||||||
|
我们已经建立了一套谈判选项的规则。
|
||||||
|
|
||||||
|
若双方同时请求一个相同的选项,则每一方都可以把对方的请求当作对自己的请求的肯定回应。
|
||||||
|
|
||||||
|
3.谈判句法的对称性可能会导致无穷尽的应答循环——每一方都把对方发送过来的命令当作必须回答的请求而不是对方的应答。为防止这种循环,可以应用下列规则:
|
||||||
|
|
||||||
|
A.一方只能请求改变选项的状态。也就是一方不能发送只声明它所使用的模式的请求。
|
||||||
|
|
||||||
|
B.如果一方接收到要求它进入当前它所在的状态的请求,那么该请求将不会被应答。这种不应答对防止无穷尽的循环是非常重要的。对于那些改变模式的请求,都需要一个应答——尽管该模式不一定改变。
|
||||||
|
|
||||||
|
C.无论何时,只要一方向第二方发送一个选项命令,不管该命令是请求还是应答,而且使用该选项将会对从第一方发送到第二方的数据的处理生产影响,那么必须把该命令插到数据流中它希望开始起作用的点上。(要注意到在传送请求和接收到可能是否定的应答的过程需要一些时间。因此,一台主机可能希望在发出选项的请求后缓冲要发送的数据,直到它知道该请求是被接受还是被拒绝,来隐藏这段对用户来说是”不确定”的时间。)
|
||||||
|
|
||||||
|
选项请求在TELENT连接刚刚建立起的时候要在在连接的两端来来回回传送许多次,每一方都试图从对方获取尽可能好的服务。另外,选项也可以用来动态地改变连接的特性,使它与对本地状态的改变相一致。例如,NVT(后面将要解释)使用的传输方式比较适合“每次一行”的应用程序(例如BASIC),但不适合那些“每次一个字符”的应用程序(比如NLS)。若对本地的处理来说是合适的,服务器可能会接受“每次一个字符”所需的巨大的处理器开销,并且会谈判一个合适的选项。然而,当不再需要细致的控制时,可以(通过谈判)切换回NVT下的状态以降低开销。
|
||||||
|
|
||||||
|
如果一个过程在收到一个拒绝回应后,仅仅是重新请求该选项,那么由一个过程发起的请求将会陷入循环。 为了防止出现这样的循环,不能重复被拒绝的请求,除非已经情况已经改变。实际中,这可能意味着该过程运行了另外一个程序,或者用户已经发出了另外的命令,或者出现了其他所有将影响一个过程及其选项的上下文的东西。根据经验,重请求应做为随后来自连接另一端的信息的回复,或由本地用户人为触发。
|
||||||
|
|
||||||
|
选项的设计者不应该拘泥于选项谈判中有限的一些语法。使用简单的语法的本意是希望使得选项易于使用 – 因为要忽略它们是很容易的。如果有一些特殊的选项需要一个比“DO,DON'T,WILL,WON'T”更完整的谈判结构,一个比较好的方法是用“DO, DON'T, WILL, WON'T”来确定双方都能理解该选项,然后,就可以自由地使用一个更为特别的语法。比如,一方可以发送一个请求来通知(建立)一行的长度。如果这个请求被另一方所接受,那么可以用另外一个不同的语法来进行实际的对一行的长度的谈判 – 如一个“子谈判”可能包括可以允许的最小值,可以允许的最大值,以及最合适的行的长度等字段。一个较为重要的原则是,这样的扩展谈判只有在前面的一些(标准)谈判已经建立,并且双方都可以解释这些扩展语法的情况下才能开始。
|
||||||
|
|
||||||
|
总之,WILL XXX由双方发送出去,用于声明该方希望(提供)开始对选项XXX进行处理。DO XXX和DON'T XXX表示它的肯定和否定回应;类似地,DO XXX发送出去指示(请求)对方(也即DO的接收者)开始对选项XXX进行处理,WILL XXX和WON'T XXX表示肯定和否定回应。
|
||||||
|
|
||||||
|
由于在没有使用任何的选项的情况下,NVT通过使用DON'T和WON'T回应来保证连接在连接的双方都可以处理的状态中。因此,所有主机都应该这样实现它们的TELNET进程:在完全不知道一个不支持的选项的情况下,只需要简单地拒绝任何无法理解的该选项请求。
|
||||||
|
|
||||||
|
TELNET协议尽可能地使服务器和用户之间是对称的,以便比较容易和自然地包含用户到用户(连接)和服务器到服务器(协作处理)这两种情况。尽管不是完全需要,但我们也希望选项能够加强这个目的。不管如何,对称性是一个操作上的原则,而不是一个不变的标准,这是公认的。
|
||||||
|
|
||||||
|
请参考相关文档“TELNET选项规范”来得到关于如何建立新的选项的信息。
|
||||||
|
|
||||||
|
## 3. 网络虚终端
|
||||||
|
|
||||||
|
网络虚终端(NVT)是一个双向的字符设备。NVT有一个打印机和一个键盘。打印机负责进来的数据,而键盘负责产生通过TELNET连接发送出去的数据,并且在需要“回显”时,同时在NVT的打印机上回显这些数据。“回显”并不要求数据一定要经过网络(尽管有一个选项可以控制该操作的”远程“模式,但并不要求主机实现该选项)。
|
||||||
|
|
||||||
|
除了在这里说明的外,所有的编码集合都是有八位的,但只使用其中的七位的USASCII码。所有的代码转换和时区方面的问题都是本地的事情,而不影响NVT。
|
||||||
|
|
||||||
|
## 4. 数据的传输
|
||||||
|
|
||||||
|
尽管一个通过网络连接的TELNET连接本质上是全双工的,但通常把NVT看作在线性缓冲模式下的半双工设备。也就是说,除非已经和对方谈判好,则以下条款(默认)适用于在TELNET连接的数据传输:
|
||||||
|
|
||||||
|
1) 在本地缓冲空间允许的可用范围内,可以在产生数据的机器上汇集数据,直到完整的一行数据已经准备好传输,或者某些在局部定义的信号明确地要求传输数据。这些信号既可以有进程产生,也可以有用户发出。
|
||||||
|
|
||||||
|
定义这个规则的动机是,对于一些主机,处理网络输入中断的代价是很高的,另外,缺省的NVT规范指定“回显”不经过网络的传输。因此,有理由在产生数据的源上缓冲一些数据。许多系统都会在输入一行结束后进行一些动作(行式打印机或者卡片打孔机经常都是这样子的),因此数据传输可以在一行数据结束时触发。另外,有时候用户或者进程会发现有必要或者应该在尚未到达行未时就提供数据;因此实现者应注意提供局部信号机制以确保所有的缓冲数据都能够被立即发送出去。
|
||||||
|
|
||||||
|
2) 当一个过程已完成向一个NVT打印机发送数据,并且输入队列中也没有来自NVT键盘需要进一步进行处理的数据(就是说,当一个在TELNET连接的一端的过程无法在另一端没有数据输入的情况下进行处理),该过程必须传输TELNET 的继续(Go Ahead,GA)命令。
|
||||||
|
|
||||||
|
这个规则并不要求在一个连接的两端上的终端都发送TELNET GA命令,因为服务器开始进行处理时,一般情况下都不需要一个特别的信号(以及断开连接信号和其他在本地定义的特性)。确切的说,TELNET GA被设计用来帮助用户在一个具有“可锁定”键盘的本地计算机(如IBM2741)上操作一个物理上的半双工终端。这类终端的说明书可能对解释GA命令的正确用法有帮助。
|
||||||
|
|
||||||
|
终端到计算机的连接总是在用户或者计算机的控制之下。任何一方都不能单方面地夺取另一方的控制;而且取得控制的一方必须明确地放弃它的控制。在终端这一方,应在硬件上支持在每次行终止的时候(也就是在用户按下“新行”的键时),它就放弃控制。此时,连接的(本地)计算机处理输入的数据,决定是否要产生输出,如果不需要的话,就把控制返回给终端。如果要产生输出,计算机维持控制,直到所有的输出都被传输完毕。
|
||||||
|
|
||||||
|
通过网络使用这种类型的终端,困难是显而易见的。“本地”计算机在看到一个行终止信号后,无法决定是否要保持控制,这个决定只能由处理这些数据的“远程”计算机作出。因此,TELNET中的GA命令提供了一个机制,使“远程”计算机(服务器)如何给“本地”计算机(用户)发送信号,告诉对方现在是给用户终端传递控制的时间。它应该并且只应该在应向终端用户赋予控制权时传输。注意,过早地传递GA命令将导致输出阻塞,由此用户可能会认为传输系统已经被暂停,因此将导致用户手工转向连接时失败。
|
||||||
|
|
||||||
|
当然,前面所说的这种情况不会在通讯过程中用户到服务器这个方向上出现。在这个方向上,可以随时发送GA,但这没有必要。同样,如果TELNET连接被应用在过程到过程的通讯中,在两个方向上都不需要发送GA。最后,对于终端到终端的通讯,在两个方向上可能都需要GA。如果一个主机打算支持终端到终端的通讯,建议主机在需要通过TELNET连接发送GA的时候,提供一个手工发信号给用户的方法。然而,在实现TELNET过程中,这一点并不是必需的。
|
||||||
|
|
||||||
|
注意:由于TELNET模型的对称性,从理论上来说,在一个TELNET连接的每一端,都必须有一个NVT。
|
||||||
|
|
||||||
|
## 5. 控制功能的标准表示
|
||||||
|
|
||||||
|
就象我们在本文档的简介中所说,TELENT协议的主要目标是在通过网络连接的终端设备和面向终端的过程之间提供一个标准的接口。早期具有这种互联性质的实验表明,大部分的服务器都实现了某些功能,但调用这些功能的方式却差别很大。对于一个要与多种服务器系统交互的用户来说,这些差别会使人沮丧。因此,TELNET协议定义了这些功能中的其中5种的标准表示。这些标准表示具有标准涵义 —— 但不是必要的(除了中断进程(IP)功能,使用TELENT协议的其他协议可能需要该功能)。也就是说,一个没有给本地用户提供某种功能的系统也没有必要给网络上的其他用户提供该功能,并且可以把该功能的标准表示当作No操作。另一方面,如果一个系统已经给本地用户提供了该功能,那么它必须给网络上那些传送该功能的标准表示的用户提供同样的功能。
|
||||||
|
|
||||||
|
中断进程 – Interrupted Process(IP)
|
||||||
|
|
||||||
|
许多系统提供挂起,中断,中止,终止用户进程的操作的功能。当用户确信他的进程已经进入了无穷尽的循环,或者不小心激活了一个并不希望激活的进程时,就要经常使用该功能。IP就是调用该功能的标准表示。该功能的实现者应注意的是,其他使用TELNET协议的协议可能要使用IP,因此若要支持这些协议则应实现此功能。
|
||||||
|
|
||||||
|
中断输出 -- Abort Output (AO)
|
||||||
|
|
||||||
|
许多系统提供了允许一个正在产生输出的进程在不向用户的终端发送输出的情况下完成运行(或者到达在完成运行后将会到达的某一个停止点)的功能。
|
||||||
|
|
||||||
|
另外,该功能的一个典型用途是清除那些已经生成但还没有实际打印(或者显示)到用户的终端上的输出。AO是调用该功能的标准表示。比如,许多子系统通常会接受一个用户的命令,然后以一个发送到用户终端的长的字符串作为回应,最后,给用户的终端发送一个“提示”字符(前面跟着 `<CR><LF>`)来表示准备接受下一个命令。如果是在传输字符串的过程中接收到AO,一个合理的实现应该停止继续传输字符串,而转向发送提示符和跟在前面的 `<CR><LF>`。(这可能同接收到IP所进行的动作有一些差别。在接收到IP时,将导致停止字符串的传输并且从子系统中退出。)
|
||||||
|
|
||||||
|
同时还需要注意到,对那些提供这种功能的服务器,可能还需要清除那些存在于系统外的缓冲机制(在网络中或者在用户的本地机器上)中的内容。完成这个过程的一个合适的方法是给用户的系统发送“同步”信号(将在下面描述)。
|
||||||
|
|
||||||
|
你在那里吗? -- Are You There (AYT)
|
||||||
|
|
||||||
|
许多系统提供了给用户提供系统仍然在运行的一些可见的(如可打印的)迹象。这个功能可以在系统在一个想象不到的很长一段时间里都没有动静时(可能是由于用户没有想象到的计算时间,或者不正常的巨大系统负荷等导致。)由用户调用。 AYT是调用该功能的标准表示.
|
||||||
|
|
||||||
|
消除一个字符 - - Erase Character (EC)
|
||||||
|
|
||||||
|
许多系统提供了删除在未删除字符前面或者用户提供的数据流中的“打印位置” 最后面的一个字符的功能。该功能通常在键盘输入时输入了错误的字符时使用。EC是调用该功能的标准表示。
|
||||||
|
|
||||||
|
*注意 :一个“打印位置”可能包含相互覆盖的几个字符,或者象下面的字符系列:`<char1>` BS `<char2>`...
|
||||||
|
|
||||||
|
消除一行 -- Erase Line (EL)
|
||||||
|
|
||||||
|
许多系统提供了删除输出设备上的当前一行的全部数据的功能。该功能经常在用键盘进行输入编辑时使用。EL是调用该功能的标准表示。
|
||||||
|
|
||||||
|
## 6. TELNET中的“同步(SYNCH)”信号
|
||||||
|
|
||||||
|
许多分时系统提供了一种机制,以允许终端用户重新获得对“失控”进程的控制权。上面描述的IP和AO功能就是这种机制的例子。当在本地使用时,这样的系统可以访问由用户提供的所有信号,而不管这些信号是一些普通字符或者是由电传打字机中的“BREAK”键或IBM 2741中的”ATTN”键发送的”带外“信号。然而当通过网络把系统联结起来时,这可能是不正确的。网络的流程控制机制可能导致把这些信号缓冲到其他地方,比如用户的机器中。
|
||||||
|
|
||||||
|
为了解决这个问题,提出了TELNET中的”同步” 机制。一个同步信号包含一个带有TELNET命令DATA MARK的TCP紧急通知。该紧急通知不受TELNET连接的流控制的影响,接收它的进程用它来调用数据流的特殊处理过程。在这种模式中,将立即开始对数据流进行扫描,查找下面定义的一些“有趣”的信号,并丢弃期间的数据。
|
||||||
|
|
||||||
|
TELNET命令DATA MARK(DM)是数据流中的同步标记,表示某个特殊的信号已经经产生,接受者可以继续对数据流进行一般的处理。
|
||||||
|
|
||||||
|
同步信号通过TCP中的发送操作发送,其紧急标志设为“真”,并且DM为作为最后(或者唯一的)一个字节。
|
||||||
|
|
||||||
|
当许多同步信号快速地连续不断地发送时,可以合并紧急通知。不可能去计算紧急通知的次数,因为接收到的紧急通知的次数可能等于或者少于发送次数。在普通模式中,一个DM是没有任何操作的,但在紧急模式中,它表示紧急处理过程的结束。
|
||||||
|
|
||||||
|
如果在发现DM之前,TCP已经指示紧急数据的结束,TELNET应该继续对数据流进行特殊的处理,直到发现DM。
|
||||||
|
|
||||||
|
如果在发现DM之后,TCP指示有更多的紧急数据,它只能是另外同步信号。TELNET应继续对数据流进行特殊的处理,直到发现另外一个DM。
|
||||||
|
|
||||||
|
“有趣的”信号定义为:TELNET中的IP, AO, 和 AYT (不包括EC 或EL)的标准表示;与这些标准表示类似的本地表示(如果有的话);所有的其他TELNET命令;其他能够起作用且不会延迟数据流扫描的自定义信号。
|
||||||
|
|
||||||
|
由于SYNCH机制的一个影响是丢弃本来在发送者和接收者之间要传输的所有字符(TELNET命令除外),如果需要,这个机制可以作为清除数据路径的一种标准方式。例如,在一个终端上的用户需要传输一个AO,接收到该AO的服务器应该给该用户返回一个同步信号(如果它提供该功能的话)。
|
||||||
|
|
||||||
|
最后,就象在TELNET层,需要把一个TCP紧急通知当作一个带外信号,因此其他使用TELNET的协议可能需要从不同层次来看可以当作带外信号的TELNET命令。
|
||||||
|
|
||||||
|
根据约定,序列[IP,Synch] 可以作为这样的信号。例如,假设有一个使用TELNET协议的其他协议定义了一个类似于TELNET命令AO的字符串STOP。想象用户使用该协议的目的是希望服务器处理STOP字符串,但由于服务器在处理其他的命令,导致连接被阻塞。用户应该引导他的系统:
|
||||||
|
|
||||||
|
a) 发送出TELNET IP字符;
|
||||||
|
|
||||||
|
b) 发送出TELNET SYNC系列,也就是:在一个紧急模式的TCP发送操作中把Data Mark (DM)作为唯一的字符发送出去。
|
||||||
|
|
||||||
|
c) 发送出字符串STOP;接着
|
||||||
|
|
||||||
|
d) 如果有的话,把其他协议中类似于TELNET DM的命令发送出去。
|
||||||
|
|
||||||
|
用户(或者代表该用户的进程)必须传输上面步骤2中的TELNET SYNCH 系列,以确保TELNET IP已经到达服务器的TELNET 解释器。
|
||||||
|
|
||||||
|
紧急通知将激活TELNET进程,而IP将激活随后级别较高的进程。
|
||||||
|
|
||||||
|
## 7. NVT打印机和键盘
|
||||||
|
|
||||||
|
NVT打印机有一个没有指定宽度的走纸器,并且每一页的长度也没有指定。NVT打印机可以产生所有95个USASCII编码的图形表示(从32到126的编码)。在33个USASCII编码(0到31及127)和未包含的其他128个编码(128到255)中,下面几个编码对NVT打印机有限定的意义:
|
||||||
|
|
||||||
|
| 名称 | 编码 | 描述 |
|
||||||
|
| --------------------- | ---- | ------------------------------------------------ |
|
||||||
|
| NULL (NUL) | 0 | 空操作 |
|
||||||
|
| Line Feed (LF) | 10 | 打印头移到下一个打印行,但不改变打印头的水平位置 |
|
||||||
|
| Carriage Return(CR) | 13 | 把打印头移到当前行的左边 |
|
||||||
|
|
||||||
|
另外,在NVT打印机上,尽管不是必需的,同时应该定义下面这些编码。TELNET连接的双方,都不会假设另一方在接收到或传输下面这些编码时将会,或者已经实施某种特殊动作:
|
||||||
|
|
||||||
|
| 名称 | 编码 | 描述 |
|
||||||
|
| --------------------- | ---- | ---------------------------------------------------------------------------------------------------------- |
|
||||||
|
| BELL (BEL) | 7 | 产生一个可以看到或可以听到的信号(而不移动打印头。) |
|
||||||
|
| Back Space (BS) | 8 | 向左移动打印头一个字符位置 |
|
||||||
|
| Horizontal Tab (HT) | 9 | 把打印头移到下一个水平制表符停止的位置。它仍然没有指定每一方如何检测或者设定如何定位这样的制表符的停止位置 |
|
||||||
|
| Vertical Tab (VT) | 11 | 把打印头移到下一个垂直制表符停止的位置。它仍然没有指定每一方如何检测或者设定如何定位这样的制表符的停止位置 |
|
||||||
|
| Form Feed (FF) | 12 | 把打印头移到下一页的顶部,保持打印头在相同的水平位置上 |
|
||||||
|
|
||||||
|
剩下的其他编码都不会导致NVT打印实施任何动作。
|
||||||
|
|
||||||
|
在定义中,序列“CR LF”将导致NVT打印头移动到下一行的左边(与系列 “LF CR”的效果是一样的)。不过,许多系统和终端并不独立处理CR和LF,为了模拟它们的效果,需要进行一些处理。 (比如,许多终端没有独立于LF的CR,但是在这样的终端上可以用退格键来模拟一个CR。)因此,必须把系列CR LF”当作一个单独的“新行”字符看待,并且在需要把它们结合在一起的时候使用它们。必须在只需要一个单独的回车键时使用系列”CR NUL”;在其他的场境中必须避免使用CR字符。这个规则可以确保系统在发现一个TELNET流中有一个字符的后面跟有CR的情况下,可以作出合理的选择:是进行“换行”功能还是进行多次的退格操作。
|
||||||
|
|
||||||
|
注意,在两个方向上(在缺省的ASCII模式下)都需要”CR LF”或者”CR NUL”,以确保NVT模式的对称性。
|
||||||
|
|
||||||
|
尽管在某种情况下(如当远程回显和禁止超前选项同时起作用时),可以认为字符并不被发送到一个实际的打印机上,然而,为了保证一致,在一个数据流中,如果一个CR的后面没有跟着一个LF,该协议要求把一个NUL插到CR的后面。
|
||||||
|
|
||||||
|
对应地,在接收方,如果从数据流中接收到一个跟在CR的后面的NUL(在没有用谈判选项显式指定其他选择的情况下),在把NVT转换成本地字符集之前,应该把NUL去掉。
|
||||||
|
|
||||||
|
NVT键盘有键或者键的组合,或者键系列来产生所有128格USAACII编码。要注意尽管一些在NVT打印机上没有什么用处,NVT键盘还是可以生成。
|
||||||
|
|
||||||
|
除了这些编码,NVT键盘还可以生成下面这些附加的编码,除注明外,还定义了这些编码的意义(尽管不是必需的)。
|
||||||
|
|
||||||
|
对这些“字符”的实际代码分配在TELNET命令这一节,因为从某种意义上来讲,我们可以认为这些编码是固有的,甚至在把数据流中的数据都解释为属于另外的一个字符集的时候,都可以使用这些编码。
|
||||||
|
|
||||||
|
Synch
|
||||||
|
|
||||||
|
这个键允许一个用户清空到另一方的数据通道。激活该键将导致发送一个带有TCP紧急通知的DM(参看命令这一节)。一对DM-紧急通知具有在前面定义的一些意义。
|
||||||
|
|
||||||
|
Break (BRK)
|
||||||
|
|
||||||
|
之所以提供这个编码,是因为在当前的许多系统中,它是USASCII集合之外的一个信号,并且具有本地意义。 可以用它来表示Break键或Attention键已被按下。然而,需要注意的是,它的目的是给需要它的系统提供第129个编码,而不等同于IP的标准表示。
|
||||||
|
|
||||||
|
Interrupt Process (IP)
|
||||||
|
|
||||||
|
挂起,中断,中止,终止一个NVT连接的进程。另外,它也是那些使用TELNET的其他协议的带外信号的一部分。
|
||||||
|
|
||||||
|
Abort Output (AO)
|
||||||
|
|
||||||
|
允许当前的进程继续运行直到结束,但不给用户发送它的输出信息。并且把一个同步信号发送给用户。
|
||||||
|
|
||||||
|
Are You There (AYT)
|
||||||
|
|
||||||
|
给NVT发送回一些可见的(也就是可打印的)信息以表明已经收到AYT。
|
||||||
|
|
||||||
|
Erase Character (EC)
|
||||||
|
|
||||||
|
接收者将删除数据流中最后一个未被删除的前导字符或者“打印位置”。
|
||||||
|
|
||||||
|
Erase Line (EL)
|
||||||
|
|
||||||
|
接收方将删除由TELNET连接发送的数据流中最后一个“CR LF”系列(但不包括该系列)后面的全部内容。
|
||||||
|
|
||||||
|
这些“额外”的键,也就是打印机的格式控制字符的本质是,它们是对从“NVT”到“本地”这个必须进行的映射过程的一个自然的扩展。
|
||||||
|
|
||||||
|
就象NVT中的字节68(八进制104),可以映射为本地中代表“大写D”的任何一个编码,字符EC也可以映射为本地中代表“删除一个字符”功能。
|
||||||
|
|
||||||
|
另外,就象在一个没有“垂直线”字符的环境下,对编码124(八进制174)的映射是任意的,如果在本地没有“删除一个字符”这种机制,对EL的映射也是任意的(甚至不映射)。
|
||||||
|
|
||||||
|
类似地,对格式控制字符,如果终端确实有一个“垂直制表键”,那么对VT地映射就是显而易见的,只有在终端没有一个垂直制表键的情况下,VT的作用才是无法预测的。
|
||||||
|
|
||||||
|
## 8. TELNET命令结构
|
||||||
|
|
||||||
|
所有的TELNET命令至少包含一个两个字节的序列:“当作命令来解释(Interpret as Command)”(IAC)的转义字符,以及紧跟的命令码。处理选项谈判的命令是三字节序列,第三个字节为选项的编码。之所以选择这种格式,是这种格式能够更大范围地使用“数据空间”(相对于基本NVT协商)。数据字节与保留的命令值的冲突被大大减少了,而所有这些冲突都需要复杂,低效的方法来把数据字节转换为流。使用此方法,只有在需要把IAC当作数据发送时才需要把相同的数据发送两次,其他255个代码都可以透明地传输。
|
||||||
|
|
||||||
|
下面是所有已定义的TELNET命令。需要注意的是,这些代码和代码序列只有在前面跟有一个IAC时才有意义。
|
||||||
|
|
||||||
|
| 名称 | 代码 | 涵义 |
|
||||||
|
| ----------------- | ---- | ------------------------------------------------------------------ |
|
||||||
|
| SE | 240 | 子谈判参数的结束 |
|
||||||
|
| NOP | 241 | 空操作 |
|
||||||
|
| DATA MARK | 242 | 一个同步信号的数据流部分。该命令的后面经常跟着一个TCP紧急通知 |
|
||||||
|
| Break | 243 | NVT的BRK字符 |
|
||||||
|
| Interrupt Process | 244 | IP功能 进程中断 |
|
||||||
|
| Abort output | 245 | AO功能 输出中断 |
|
||||||
|
| Are You There | 246 | AYT功能 |
|
||||||
|
| Erase character | 247 | EC功能 删除字符 |
|
||||||
|
| Erase Line | 248 | EL功能 删除行 |
|
||||||
|
| Go ahead | 249 | GA信号 继续 |
|
||||||
|
| SB | 250 | 表示后面所跟的是对需要的选项的子谈判 |
|
||||||
|
| WILL | 251 | 表示希望开始使用或者确认所使用的是指定的选项 |
|
||||||
|
| WON'T | 252 | 表示拒绝使用或者继续使用指定的选项 |
|
||||||
|
| DO | 253 | 表示一方要求另一方使用,或者确认你希望另一方使用指定的选项 |
|
||||||
|
| DON'T | 254 | 表示一方要求另一方停止使用,或者确认你不再希望另一方使用指定的选项 |
|
||||||
|
| IAC | 255 | Data Byte 255 |
|
||||||
|
|
||||||
|
## 9. 连接的建立
|
||||||
|
|
||||||
|
TELNET TCP连接是在用户端口U和服务器端口L之间建立的。服务器在用于这种类型的连接的一个众所周知的端口L上监听客户请求。由于一个TPC连接是全双工的,并且通过双方的端口来标识,服务器可以对不同的用户端口U和端口L的之间的许多并发连接进行应答。
|
||||||
|
|
||||||
|
端口分配
|
||||||
|
|
||||||
|
当用来给远程用户提供访问服务主机的服务(也就是远程终端访问)时,此协议分配的服务端口是23(八进制27)。也就是L=23。
|
||||||
|
|
||||||
|
# RFC 930 获取客户端类型
|
||||||
|
|
||||||
|
首先使用 IAC命令启用该功能:
|
||||||
|
|
||||||
|
IAC WILL 24
|
||||||
|
|
||||||
|
然后发送
|
||||||
|
|
||||||
|
IAC SB 24, 1, IAC, SE
|
||||||
|
|
||||||
|
等待一段时间后接收到以下字符串
|
||||||
|
|
||||||
|
IAC SB 24 0 n1,n2,n3.... IAC SE
|
||||||
|
|
||||||
|
其中 n1....nx 就是客户端类型(字符串格式)
|
||||||
|
|
||||||
|
# RFC1184 行显示控制
|
||||||
|
|
||||||
|
## 从RFC1116变更的内容:
|
||||||
|
|
||||||
|
添加了两个新的模式位,SOFT_TAB和LIT_ECHO。这些位允许服务器向客户端提供一些关于如何回显制表符和非打印字符的建议。
|
||||||
|
|
||||||
|
当支持视觉编辑时,添加了几个新的特殊字符映射,用于光标移动。这些包括:将光标向左/向右移动一个字符(SLC_MCL/SLC_MCR),将光标向左/向右移动一个单词(SLC_MCWL/SLC_MCWR),将光标移动到行首/行尾(SLC_MCBOL/SLC_MCEOL),进入插入/覆盖模式(SLC_INSRT/SLC_OVER),向右删除一个字符/单词(SLC_ECR/SLC_EWR),以及删除到行首/行尾(SLC_EBOL/SLC_EEOL)。
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
Linemode Telnet是一种在Telnet连接客户端进行终端字符处理的方式。当处于Linemode模式并且本地端启用编辑功能时,网络流量将减少到每行命令几个数据包,而不是每个输入字符几个数据包。这对于具有较长延迟的网络来说非常有用,因为用户在输入命令行时可以获得本地响应时间,只在命令输入完毕后才会遇到网络延迟。此外,它也有助于减少按数据包收费的网络的成本。
|
||||||
|
|
||||||
|
### 打开该功能:
|
||||||
|
|
||||||
|
IAC WILL 34
|
||||||
|
|
||||||
|
### 选项:
|
||||||
|
|
||||||
|
IAC SB 34 MODE mask IAC SE
|
||||||
|
|
||||||
|
MODE :
|
||||||
|
|
||||||
|
| 序号 | 命令名称 | 代码 |
|
||||||
|
| ---- | -------- | ---- |
|
||||||
|
| 1 | EDIT | 1 |
|
||||||
|
| 2 | TRAPSIG | 2 |
|
||||||
|
| 3 | MODE_ACK | 4 |
|
||||||
|
| 4 | SOFT_TAB | 8 |
|
||||||
|
| 5 | LIT_ECHO | 16 |
|
||||||
|
|
||||||
|
| 命令名称 | 描述 |
|
||||||
|
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| EDIT | 当设置时,连接的客户端应处理所有输入行,执行任何编辑功能,并仅将完成的行发送到远程端。当未设置时,客户端不应处理来自用户的任何输入,服务器端应负责处理所有需要完成的字符处理。 |
|
||||||
|
| TRAPSIG | 当设置时,客户端应将适当的中断/信号转换为它们的Telnet等效项。(这些将是IP、BRK、AYT、ABORT、EOF和SUSP)当未设置时,客户端应将中断/信号作为它们的正常ASCII值传递。 |
|
||||||
|
| FLOW | 逻辑上,这属于“mask”。然而,这将与Telnet的TOGGLE-FLOW-CONTROL选项重叠,因此使用Telnet的TOGGLE-FLOW-CONTROL选项代替。当DO/WILL LINEMODE被协商时,也应协商DO/WILL TOGGLE-FLOW-CONTROL。有关正确使用,请参阅RFC 1080,“Telnet远程流量控制”。 |
|
||||||
|
| ECHO | 逻辑上,这属于“mask”。然而,这与Telnet的ECHO选项重叠,因此使用Telnet的ECHO选项代替。客户端不应协商“WILL ECHO”。当服务器协商了“WILL ECHO”时,客户端不应将用户输入的数据回显给用户。当服务器协商了“WONT ECHO”时,客户端负责将用户输入的数据回显给用户。有关Telnet ECHO选项使用的完整讨论,请参阅RFC 857,“Telnet ECHO OPTION”。 |
|
||||||
|
| SOFT_TAB | 当设置时,客户端应将水平制表符(HT)代码(USASCII 9)扩展为适当数量的空格,以便将打印机移动到下一个水平制表符停止位置。当未设置时,客户端应允许水平制表符代码未经修改地通过。 |
|
||||||
|
| LIT_ECHO | 当设置时,如果客户端正在将用户输入的非打印字符回显到用户屏幕上,则应将字符作为字面字符回显。如果未设置LIT_ECHO位,则客户端可以以任何它想要的方式回显字符。(许多系统将非打印字符回显为两个字符的序列,例如,它们会将ASCII值为1的字符回显为“^A”。) |
|
||||||
|
|
||||||
|
当连接的客户端接收到MODE命令时,它必须至少同意EDIT和TRAPSIG位的状态。如果接收到一个当前正在使用的模式掩码(忽略MODE_ACK位)的MODE命令,则该MODE命令将被忽略。如果接收到的MODE命令与当前模式掩码不同,则发送带有新模式掩码和MODE_ACK位设置的回复,或者发送新模式掩码的子集。唯一的例外是,如果服务器接收到EDIT或TRAPSIG位未设置的MODE,它可以在响应中设置EDIT和TRAPSIG位,而如果客户端接收到EDIT或TRAPSIG位设置的MODE,它不能在响应中清除这些位。
|
||||||
|
|
||||||
|
当接收到MODE_ACK位设置的MODE命令,且该模式与当前模式不同时,客户端将忽略新模式,而服务器将切换到新模式。这确保了连接的两端都将解析为相同的模式。在所有情况下,对于设置了MODE_ACK位的MODE命令,永远不会生成响应。
|
||||||
|
|
||||||
|
### 子选项
|
||||||
|
|
||||||
|
IAC SB LINEMODE DO FORWARDMASK mask0 mask1 ... mask31 IAC SE
|
||||||
|
|
||||||
|
这条命令的发送方请求对方在接收到由位掩码定义的任何ASCII字符时,发送任何缓冲的数据。只有发送DO LINEMODE命令的连接方(即服务器端)可以协商此选项。掩码的长度最多为32个八位字节。每个八位字节代表8个ASCII字符编码。mask0的最高位对应于ASCII码0,而mask0的最低位对应于ASCII码7。mask1的最高位对应于ASCII码8,而mask1的最低位对应于ASCII码15,以此类推。掩码列表可以在列表结束之前终止,在这种情况下,假设掩码八位字节的其余部分都被重置(等于零)。当服务器端处于DONT TRANSMIT-BINARY模式时,则仅使用掩码的前16个八位字节(ASCII码0到127)。如果掩码的任何单个八位字节等于IAC,则必须将其发送为双IAC。
|
|
@ -0,0 +1,69 @@
|
||||||
|
/** function comment
|
||||||
|
* @Author: 陈逸凡 1343619937@qq.com
|
||||||
|
* @Date: 2024-04-17 15:29:56
|
||||||
|
* @LastEditors: 陈逸凡 1343619937@qq.com
|
||||||
|
* @LastEditTime: 2024-04-18 16:25:48
|
||||||
|
* @FilePath: \telnet\telnet_client.c
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
#define SERVER_IP "127.0.0.1"
|
||||||
|
#define SERVER_PORT 23
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int sockfd;
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
ssize_t bytes_read;
|
||||||
|
|
||||||
|
// 创建socket
|
||||||
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
{
|
||||||
|
perror("socket creation failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置服务器地址结构
|
||||||
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(SERVER_PORT);
|
||||||
|
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
|
||||||
|
|
||||||
|
// 连接到服务器
|
||||||
|
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
|
||||||
|
{
|
||||||
|
perror("connection failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf(" connect success\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 接收数据
|
||||||
|
bytes_read = recv(sockfd, buffer, BUFFER_SIZE - 1, 0);
|
||||||
|
if (bytes_read == -1)
|
||||||
|
{
|
||||||
|
perror("recv failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i <bytes_read ; i++)
|
||||||
|
{
|
||||||
|
printf("%d ", buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭socket
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,549 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "telnet.h"
|
||||||
|
#define TELNET_PORT 223
|
||||||
|
#define RX_BUFFER_SIZE 1024
|
||||||
|
#define CMD_SIZE 1024
|
||||||
|
#define TEL_PROMPT "admin@telnet:~$ "
|
||||||
|
#define PASSWD "admin"
|
||||||
|
// extern void printp(char *format, ...);
|
||||||
|
// #define debug_print(fmt, ...) printp(fmt, ##__VA_ARGS__)
|
||||||
|
// #define debug_print(fmt...) printp(...)
|
||||||
|
#define debug_print(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
typedef struct telnet_t
|
||||||
|
{
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
int sock_server;
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
int sock_client;
|
||||||
|
unsigned char rec_buff[RX_BUFFER_SIZE];
|
||||||
|
int rec_len;
|
||||||
|
unsigned char cmd_buff[CMD_SIZE];
|
||||||
|
int cmd_pos;
|
||||||
|
unsigned short win_width;
|
||||||
|
unsigned short win_height;
|
||||||
|
unsigned char cilent_type_name[10];
|
||||||
|
char cilent_type;
|
||||||
|
char *passwd;
|
||||||
|
char passwd_pos;
|
||||||
|
char *tel_prompt;
|
||||||
|
char init : 1;
|
||||||
|
char login_in : 1;
|
||||||
|
char tel_login_show : 1;
|
||||||
|
char f_echo : 1;
|
||||||
|
} telnet_t;
|
||||||
|
|
||||||
|
telnet_t telnet = {
|
||||||
|
.passwd = PASSWD,
|
||||||
|
.tel_prompt = TEL_PROMPT,
|
||||||
|
};
|
||||||
|
int telnet_init(telnet_t *tel, int port)
|
||||||
|
{
|
||||||
|
int telnet_addr_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
// server socket create
|
||||||
|
tel->sock_server = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (tel->sock_server < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: opening socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// server socket set
|
||||||
|
int keepalive = 1;
|
||||||
|
if (setsockopt(tel->sock_server, SOL_SOCKET, SO_REUSEADDR, (void *)&keepalive, sizeof(keepalive)) < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet:set socket keepalive failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// server socket bind and start listen
|
||||||
|
tel->server_addr.sin_family = AF_INET;
|
||||||
|
tel->server_addr.sin_port = htons(port);
|
||||||
|
tel->server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
if (bind(tel->sock_server, (void *)&tel->server_addr, sizeof(tel->server_addr)))
|
||||||
|
{
|
||||||
|
debug_print("error: binding tcp socket ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (listen(tel->sock_server, 1) == -1)
|
||||||
|
{
|
||||||
|
debug_print("error: listen");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
debug_print("telnet: telnet server init success\n");
|
||||||
|
tel->init = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define send_will(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = WILL; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_wont(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = WONT; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_do(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = DO; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
#define send_dont(buf, a) \
|
||||||
|
{ \
|
||||||
|
buf[0] = IAC; \
|
||||||
|
buf[1] = DONT; \
|
||||||
|
buf[2] = a; \
|
||||||
|
send(tel->sock_client, buf, 3, 0); \
|
||||||
|
};
|
||||||
|
|
||||||
|
int read_terminal_type(telnet_t *tel)
|
||||||
|
{
|
||||||
|
unsigned char terminal[] = {IAC, SB, TELOPT_TTYPE, 1, IAC, SE};
|
||||||
|
send(tel->sock_client, terminal, sizeof(terminal), 0);
|
||||||
|
sleep(1);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
if (tel->rec_len < 0)
|
||||||
|
{
|
||||||
|
debug_print("error \n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_config(telnet_t *tel)
|
||||||
|
{
|
||||||
|
if (tel->sock_client < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char cmd[3];
|
||||||
|
// send_dont(cmd, TELOPT_LINEMODE);
|
||||||
|
// send(tel->sock_client,"\033[7e",sizeof("\033[7e"),0);
|
||||||
|
// send_do(cmd, 24);
|
||||||
|
send_will(cmd, TELOPT_ECHO);
|
||||||
|
send_will(cmd, TELOPT_SGA);
|
||||||
|
send_wont(cmd, TELOPT_LINEMODE);
|
||||||
|
|
||||||
|
// unsigned char line_mode={IAC,SB,TELOPT_LINEMODE,1,0xf,IAC,SE};
|
||||||
|
// send(tel->sock_client,line_mode,sizeof(line_mode),0);
|
||||||
|
// 清理下之前的信息
|
||||||
|
// tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_do(cmd, TELOPT_TTYPE);
|
||||||
|
// 获取下终端类型
|
||||||
|
unsigned char terminal[] = {IAC, SB, TELOPT_TTYPE, 1, IAC, SE};
|
||||||
|
send(tel->sock_client, terminal, sizeof(terminal), 0);
|
||||||
|
// send_wont(cmd, TELOPT_LINEMODE);
|
||||||
|
// send_dont(cmd, TELOPT_LINEMODE);
|
||||||
|
// send
|
||||||
|
// send
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* 客户端会按照顺序进行回复
|
||||||
|
*/
|
||||||
|
unsigned char cmd[3];
|
||||||
|
send_do(cmd, 24);
|
||||||
|
send_do(cmd, 32);
|
||||||
|
send_do(cmd, 35);
|
||||||
|
send_do(cmd, 39);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
tel->cilent_type = 0;
|
||||||
|
if (tel->rec_len < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tel->rec_len == 12)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 12; i++)
|
||||||
|
{
|
||||||
|
if (tel->rec_buff[i] == 32 && tel->rec_buff[i - 1] == WONT)
|
||||||
|
{
|
||||||
|
// busy client
|
||||||
|
tel->cilent_type = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->cilent_type = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// cilent_type = 3;
|
||||||
|
switch (tel->cilent_type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
send_will(cmd, 3);
|
||||||
|
send_do(cmd, 1);
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 5);
|
||||||
|
send_do(cmd, 33);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_will(cmd, 1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
send_will(cmd, 3);
|
||||||
|
send_do(cmd, 1);
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 5);
|
||||||
|
send_do(cmd, 33);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_will(cmd, 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 1);
|
||||||
|
send_do(cmd, 3);
|
||||||
|
send_will(cmd, 3);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_do(cmd, 1);
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 5);
|
||||||
|
send_do(cmd, 33);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 3);
|
||||||
|
send_do(cmd, 1);
|
||||||
|
send_do(cmd, 31);
|
||||||
|
send_will(cmd, 5);
|
||||||
|
send_do(cmd, 33);
|
||||||
|
send_dont(cmd, 1);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_dont(cmd, 1);
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
send_will(cmd, 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int telnet_cmd_handle(telnet_t *tel)
|
||||||
|
{
|
||||||
|
|
||||||
|
send(tel->sock_client, tel->cmd_buff, tel->cmd_pos, 0);
|
||||||
|
|
||||||
|
tel->cmd_pos = 0;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
int telnet_shell_handle(telnet_t *tel, char c)
|
||||||
|
{
|
||||||
|
if (c == 13)
|
||||||
|
{
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
telnet_cmd_handle(tel);
|
||||||
|
send(tel->sock_client, "\r\n", 2, 0);
|
||||||
|
// send(tel->sock_client,"123",3,0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
// send(tel->sock_client, " ", 1, 0);
|
||||||
|
unsigned char clear_line[] = "\r\033[K";
|
||||||
|
send(tel->sock_client, clear_line, sizeof(clear_line), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (c == 0)
|
||||||
|
{
|
||||||
|
send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else if (c == 10)
|
||||||
|
{
|
||||||
|
send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else if (c == 9)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tel->cmd_pos < CMD_SIZE)
|
||||||
|
{
|
||||||
|
tel->cmd_buff[tel->cmd_pos++] = c;
|
||||||
|
send(tel->sock_client, &c, 1, 0);
|
||||||
|
send(tel->sock_client, " ", 1, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send(tel->sock_client, " ", 2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_nor_handle(telnet_t *tel, char c)
|
||||||
|
{
|
||||||
|
if (tel->f_echo == 0)
|
||||||
|
{
|
||||||
|
char cmd[3] = {0x08, ' ', 0x08};
|
||||||
|
send(tel->sock_client, cmd, 3, 0);
|
||||||
|
}
|
||||||
|
if (tel->login_in == 0)
|
||||||
|
{
|
||||||
|
if (tel->tel_login_show == 0)
|
||||||
|
{
|
||||||
|
char cmd[] = "\033[?25l";
|
||||||
|
send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->tel_login_show = 1;
|
||||||
|
}
|
||||||
|
// 无论如何回复一个空格
|
||||||
|
send(tel->sock_client, " ", 1, 0);
|
||||||
|
if (tel->passwd[tel->passwd_pos] == c)
|
||||||
|
{
|
||||||
|
tel->passwd_pos++;
|
||||||
|
if (tel->passwd[tel->passwd_pos] == '\0')
|
||||||
|
{
|
||||||
|
tel->login_in = 1;
|
||||||
|
tel->passwd_pos = 0;
|
||||||
|
send(tel->sock_client, "\r\nlogin success\r\n", 17, 0);
|
||||||
|
send(tel->sock_client, tel->tel_prompt, sizeof(TEL_PROMPT), 0);
|
||||||
|
if (tel->tel_login_show == 1)
|
||||||
|
{
|
||||||
|
char cmd[] = "\033[?25h";
|
||||||
|
send(tel->sock_client, cmd, sizeof(cmd), 0);
|
||||||
|
tel->tel_login_show = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tel->passwd_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// telnet_shell_handle(tel, c);
|
||||||
|
// char see = 0;
|
||||||
|
telnet_shell_handle(tel, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_rec_handle(telnet_t *tel, unsigned char *c, int len)
|
||||||
|
{
|
||||||
|
#define MOD_NORMAL 0
|
||||||
|
#define MOD_IAC 1
|
||||||
|
#define MOD_WILL 2
|
||||||
|
#define MOD_WONT 3
|
||||||
|
#define MOD_DO 4
|
||||||
|
#define MOD_DONT 5
|
||||||
|
#define MOD_SB 6
|
||||||
|
int state = MOD_NORMAL;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case MOD_NORMAL:
|
||||||
|
if (c[i] == IAC)
|
||||||
|
{
|
||||||
|
state = MOD_IAC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_IAC:
|
||||||
|
if (c[i] == IAC)
|
||||||
|
{
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
// 2个IAC代表字符255,也需要进行处理
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
else if (c[i] == DO)
|
||||||
|
{
|
||||||
|
state = MOD_DO;
|
||||||
|
}
|
||||||
|
else if (c[i] == DONT)
|
||||||
|
{
|
||||||
|
state = MOD_DONT;
|
||||||
|
}
|
||||||
|
else if (c[i] == WILL)
|
||||||
|
{
|
||||||
|
state = MOD_WILL;
|
||||||
|
}
|
||||||
|
else if (c[i] == WONT)
|
||||||
|
{
|
||||||
|
state = MOD_WONT;
|
||||||
|
}
|
||||||
|
else if (c[i] == SB)
|
||||||
|
{
|
||||||
|
state = MOD_SB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
telnet_nor_handle(tel, c[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WILL:
|
||||||
|
debug_print("telnet: WILL %d\n", c[i]);
|
||||||
|
if (c[i] == TELOPT_NAWS)
|
||||||
|
{
|
||||||
|
if (c[i + 1] == IAC && c[i + 2] == SB && c[i + 3] == TELOPT_NAWS && c[i + 8] == IAC && c[i + 9] == SE)
|
||||||
|
{
|
||||||
|
tel->win_width = ((unsigned short)c[i + 4] << 8) + (unsigned short)c[i + 5];
|
||||||
|
tel->win_height = ((unsigned short)c[i + 6] << 8) + (unsigned short)c[i + 7];
|
||||||
|
i = i + 9;
|
||||||
|
debug_print("telnet: win_width = %d, win_height = %d\n", tel->win_width, tel->win_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_WONT:
|
||||||
|
debug_print("telnet: WONT %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_DO:
|
||||||
|
|
||||||
|
debug_print("telnet: DO %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_DONT:
|
||||||
|
if (c[i] == TELOPT_ECHO)
|
||||||
|
{
|
||||||
|
tel->f_echo = 0;
|
||||||
|
}
|
||||||
|
debug_print("telnet: DONT %d\n", c[i]);
|
||||||
|
state = MOD_NORMAL;
|
||||||
|
break;
|
||||||
|
case MOD_SB:
|
||||||
|
if (c[i] == TELOPT_TTYPE && c[i + 1] == 0)
|
||||||
|
{
|
||||||
|
i = i + 2;
|
||||||
|
int k = 0;
|
||||||
|
// 客户端类型
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((c[i] == IAC && c[i + 1] == SE) || i == len)
|
||||||
|
{
|
||||||
|
tel->cilent_type_name[k] = '\0';
|
||||||
|
printf("telnet: client type = %s\n", tel->cilent_type_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tel->cilent_type_name[k] = c[i];
|
||||||
|
i++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int telnet_core(telnet_t *tel)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (tel->init == 0)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
debug_print("\ntelnet: waiting for connection\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int addr_len = sizeof(tel->client_addr);
|
||||||
|
tel->sock_client = accept(tel->sock_server, (void *)&tel->client_addr, &addr_len);
|
||||||
|
if (tel->sock_client < 0)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_print("telnet: new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(tel->client_addr.sin_addr), tel->client_addr.sin_port);
|
||||||
|
int ret = telnet_config(tel);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: client disconnected\n");
|
||||||
|
close(tel->sock_client);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tel->login_in == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
send(tel->sock_client, "admin login: \r\n", 15, 0);
|
||||||
|
}
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// telnet_host_function();
|
||||||
|
tel->rec_len = recv(tel->sock_client, tel->rec_buff, RX_BUFFER_SIZE, 0);
|
||||||
|
// if (tel->rec_buff[0] == IAC && tel->rec_buff[1] != IAC)
|
||||||
|
// {
|
||||||
|
// telnet_config_back(tel);
|
||||||
|
// }
|
||||||
|
if (tel->rec_len > 0)
|
||||||
|
{
|
||||||
|
debug_print("telnet: recv_len = %d\n", tel->rec_len);
|
||||||
|
for (int i = 0; i < tel->rec_len; i++)
|
||||||
|
{
|
||||||
|
switch (tel->rec_buff[i])
|
||||||
|
{
|
||||||
|
case IAC:
|
||||||
|
debug_print("IAC,");
|
||||||
|
break;
|
||||||
|
case DO:
|
||||||
|
debug_print("DO,");
|
||||||
|
break;
|
||||||
|
case DONT:
|
||||||
|
debug_print("DONT,");
|
||||||
|
break;
|
||||||
|
case WILL:
|
||||||
|
debug_print("WILL,");
|
||||||
|
break;
|
||||||
|
case WONT:
|
||||||
|
debug_print("WONT,");
|
||||||
|
break;
|
||||||
|
case SB:
|
||||||
|
debug_print("SB,");
|
||||||
|
break;
|
||||||
|
case SE:
|
||||||
|
debug_print("SE,");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug_print("%d,", tel->rec_buff[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_print("\n");
|
||||||
|
telnet_rec_handle(tel, tel->rec_buff, tel->rec_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug_print("telnet: client disconnected\n");
|
||||||
|
tel->login_in = 0;
|
||||||
|
close(tel->sock_client);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
telnet_init(&telnet, TELNET_PORT);
|
||||||
|
telnet_core(&telnet);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue