📄 telnet.c
字号:
*/
if (n || (cp - cp2 > 41))
;
else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
*argv = cp2;
else if (is_unique(cp2, argv+1, argvp))
*argvp++ = cp2;
if (c == ':')
break;
/*
* Skip multiple delimiters. Reset cp2 to
* the beginning of the next name. Reset n,
* the flag for names with spaces.
*/
while ((c = *cp) == '|')
cp++;
cp2 = cp;
n = 0;
}
/*
* Skip entries with spaces or non-ascii values.
* Convert lower case letters to upper case.
*/
if ((c == ' ') || !isascii(c))
n = 1;
else if (islower(c))
*cp = toupper(c);
}
/*
* Check for an old V6 2 character name. If the second
* name points to the beginning of the buffer, and is
* only 2 characters long, move it to the end of the array.
*/
if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
--argvp;
for (avt = &argv[1]; avt < argvp; avt++)
*avt = *(avt+1);
*argvp++ = buf;
}
/*
* Duplicate last name, for TTYPE option, and null
* terminate the array. If we didn't find a match on
* our terminal name, put that name at the beginning.
*/
cp = *(argvp-1);
*argvp++ = cp;
*argvp = 0;
if (*argv == 0) {
if (name)
*argv = name;
else {
--argvp;
for (avt = argv; avt < argvp; avt++)
*avt = *(avt+1);
}
}
if (*argv)
return(argv);
else
return(unknown);
}
int
is_unique(name, as, ae)
register char *name, **as, **ae;
{
register char **ap;
register int n;
n = strlen(name) + 1;
for (ap = as; ap < ae; ap++)
if (strncasecmp(*ap, name, n) == 0)
return(0);
return (1);
}
#ifdef TERMCAP
char termbuf[1024];
/*ARGSUSED*/
int
setupterm(tname, fd, errp)
char *tname;
int fd, *errp;
{
if (tgetent(termbuf, tname) == 1) {
termbuf[1023] = '\0';
if (errp)
*errp = 1;
return(0);
}
if (errp)
*errp = 0;
return(-1);
}
#else
#define termbuf ttytype
extern char ttytype[];
#endif
int resettermname = 1;
char *
gettermname()
{
char *tname;
static char **tnamep = 0;
static char **next;
int err;
if (resettermname) {
resettermname = 0;
if (tnamep && tnamep != unknown)
free(tnamep);
if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
(setupterm(tname, 1, &err) == 0)) {
tnamep = mklist(termbuf, tname);
} else {
if (tname && ((int)strlen(tname) <= 40)) {
unknown[0] = tname;
upcase(tname);
} else
unknown[0] = name_unknown;
tnamep = unknown;
}
next = tnamep;
}
if (*next == 0)
next = tnamep;
return(*next++);
}
/*
* suboption()
*
* Look at the sub-option buffer, and try to be helpful to the other
* side.
*
* Currently we recognize:
*
* Terminal type, send request.
* Terminal speed (send request).
* Local flow control (is request).
* Linemode
*/
static void
suboption()
{
unsigned char subchar;
printsub('<', subbuffer, SB_LEN()+2);
switch (subchar = SB_GET()) {
case TELOPT_TTYPE:
if (my_want_state_is_wont(TELOPT_TTYPE))
return;
if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
return;
} else {
char *name;
unsigned char temp[50];
int len;
#if defined(TN3270)
if (tn3270_ttype()) {
return;
}
#endif /* defined(TN3270) */
name = gettermname();
len = strlen(name) + 4 + 2;
if (len < NETROOM()) {
sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
TELQUAL_IS, name, IAC, SE);
ring_supply_data(&netoring, temp, len);
printsub('>', &temp[2], len-2);
} else {
ExitString("No room in buffer for terminal type.\n", 1);
/*NOTREACHED*/
}
}
break;
case TELOPT_TSPEED:
if (my_want_state_is_wont(TELOPT_TSPEED))
return;
if (SB_EOF())
return;
if (SB_GET() == TELQUAL_SEND) {
long ospeed, ispeed;
unsigned char temp[50];
int len;
TerminalSpeeds(&ispeed, &ospeed);
sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
TELQUAL_IS, ospeed, ispeed, IAC, SE);
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
if (len < NETROOM()) {
ring_supply_data(&netoring, temp, len);
printsub('>', temp+2, len - 2);
}
/*@*/ else printf("lm_will: not enough room in buffer\n");
}
break;
case TELOPT_LFLOW:
if (my_want_state_is_wont(TELOPT_LFLOW))
return;
if (SB_EOF())
return;
switch(SB_GET()) {
case LFLOW_RESTART_ANY:
restartany = 1;
break;
case LFLOW_RESTART_XON:
restartany = 0;
break;
case LFLOW_ON:
localflow = 1;
break;
case LFLOW_OFF:
localflow = 0;
break;
default:
return;
}
setcommandmode();
setconnmode(0);
break;
case TELOPT_LINEMODE:
if (my_want_state_is_wont(TELOPT_LINEMODE))
return;
if (SB_EOF())
return;
switch (SB_GET()) {
case WILL:
lm_will(subpointer, SB_LEN());
break;
case WONT:
lm_wont(subpointer, SB_LEN());
break;
case DO:
lm_do(subpointer, SB_LEN());
break;
case DONT:
lm_dont(subpointer, SB_LEN());
break;
case LM_SLC:
slc(subpointer, SB_LEN());
break;
case LM_MODE:
lm_mode(subpointer, SB_LEN(), 0);
break;
default:
break;
}
break;
#ifdef OLD_ENVIRON
case TELOPT_OLD_ENVIRON:
#endif
case TELOPT_NEW_ENVIRON:
if (SB_EOF())
return;
switch(SB_PEEK()) {
case TELQUAL_IS:
case TELQUAL_INFO:
if (my_want_state_is_dont(subchar))
return;
break;
case TELQUAL_SEND:
if (my_want_state_is_wont(subchar)) {
return;
}
break;
default:
return;
}
env_opt(subpointer, SB_LEN());
break;
case TELOPT_XDISPLOC:
if (my_want_state_is_wont(TELOPT_XDISPLOC))
return;
if (SB_EOF())
return;
if (SB_GET() == TELQUAL_SEND) {
unsigned char temp[50], *dp;
int len;
if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
/*
* Something happened, we no longer have a DISPLAY
* variable. So, turn off the option.
*/
send_wont(TELOPT_XDISPLOC, 1);
break;
}
sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
TELQUAL_IS, dp, IAC, SE);
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
if (len < NETROOM()) {
ring_supply_data(&netoring, temp, len);
printsub('>', temp+2, len - 2);
}
/*@*/ else printf("lm_will: not enough room in buffer\n");
}
break;
#if defined(AUTHENTICATION)
case TELOPT_AUTHENTICATION: {
if (!autologin)
break;
if (SB_EOF())
return;
switch(SB_GET()) {
case TELQUAL_IS:
if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
return;
auth_is(subpointer, SB_LEN());
break;
case TELQUAL_SEND:
if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
return;
auth_send(subpointer, SB_LEN());
break;
case TELQUAL_REPLY:
if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
return;
auth_reply(subpointer, SB_LEN());
break;
case TELQUAL_NAME:
if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
return;
auth_name(subpointer, SB_LEN());
break;
}
}
break;
#endif
#ifdef ENCRYPTION
case TELOPT_ENCRYPT:
if (SB_EOF())
return;
switch(SB_GET()) {
case ENCRYPT_START:
if (my_want_state_is_dont(TELOPT_ENCRYPT))
return;
encrypt_start(subpointer, SB_LEN());
break;
case ENCRYPT_END:
if (my_want_state_is_dont(TELOPT_ENCRYPT))
return;
encrypt_end();
break;
case ENCRYPT_SUPPORT:
if (my_want_state_is_wont(TELOPT_ENCRYPT))
return;
encrypt_support(subpointer, SB_LEN());
break;
case ENCRYPT_REQSTART:
if (my_want_state_is_wont(TELOPT_ENCRYPT))
return;
encrypt_request_start(subpointer, SB_LEN());
break;
case ENCRYPT_REQEND:
if (my_want_state_is_wont(TELOPT_ENCRYPT))
return;
/*
* We can always send an REQEND so that we cannot
* get stuck encrypting. We should only get this
* if we have been able to get in the correct mode
* anyhow.
*/
encrypt_request_end();
break;
case ENCRYPT_IS:
if (my_want_state_is_dont(TELOPT_ENCRYPT))
return;
encrypt_is(subpointer, SB_LEN());
break;
case ENCRYPT_REPLY:
if (my_want_state_is_wont(TELOPT_ENCRYPT))
return;
encrypt_reply(subpointer, SB_LEN());
break;
case ENCRYPT_ENC_KEYID:
if (my_want_state_is_dont(TELOPT_ENCRYPT))
return;
encrypt_enc_keyid(subpointer, SB_LEN());
break;
case ENCRYPT_DEC_KEYID:
if (my_want_state_is_wont(TELOPT_ENCRYPT))
return;
encrypt_dec_keyid(subpointer, SB_LEN());
break;
default:
break;
}
break;
#endif /* ENCRYPTION */
default:
break;
}
}
static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
void
lm_will(cmd, len)
unsigned char *cmd;
int len;
{
if (len < 1) {
/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
return;
}
switch(cmd[0]) {
case LM_FORWARDMASK: /* We shouldn't ever get this... */
default:
str_lm[3] = DONT;
str_lm[4] = cmd[0];
if (NETROOM() > sizeof(str_lm)) {
ring_supply_data(&netoring, str_lm, sizeof(str_lm));
printsub('>', &str_lm[2], sizeof(str_lm)-2);
}
/*@*/ else printf("lm_will: not enough room in buffer\n");
break;
}
}
void
lm_wont(cmd, len)
unsigned char *cmd;
int len;
{
if (len < 1) {
/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
return;
}
switch(cmd[0]) {
case LM_FORWARDMASK: /* We shouldn't ever get this... */
default:
/* We are always DONT, so don't respond */
return;
}
}
void
lm_do(cmd, len)
unsigned char *cmd;
int len;
{
if (len < 1) {
/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
return;
}
switch(cmd[0]) {
case LM_FORWARDMASK:
default:
str_lm[3] = WONT;
str_lm[4] = cmd[0];
if (NETROOM() > sizeof(str_lm)) {
ring_supply_data(&netoring, str_lm, sizeof(str_lm));
printsub('>', &str_lm[2], sizeof(str_lm)-2);
}
/*@*/ else printf("lm_do: not enough room in buffer\n");
break;
}
}
void
lm_dont(cmd, len)
unsigned char *cmd;
int len;
{
if (len < 1) {
/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
return;
}
switch(cmd[0]) {
case LM_FORWARDMASK:
default:
/* we are always WONT, so don't respond */
break;
}
}
static unsigned char str_lm_mode[] = {
IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
};
void
lm_mode(cmd, len, init)
unsigned char *cmd;
int len, init;
{
if (len != 1)
return;
if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
return;
if (*cmd&MODE_ACK)
return;
linemode = *cmd&(MODE_MASK&~MODE_ACK);
str_lm_mode[4] = linemode;
if (!init)
str_lm_mode[4] |= MODE_ACK;
if (NETROOM() > sizeof(str_lm_mode)) {
ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
}
/*@*/ else printf("lm_mode: not enough room in buffer\n");
setconnmode(0); /* set changed mode */
}
/*
* slc()
* Handle special character suboption of LINEMODE.
*/
struct spc {
cc_t val;
cc_t *valp;
char flags; /* Current flags & level */
char mylevel; /* Maximum level & flags */
} spc_data[NSLC+1];
#define SLC_IMPORT 0
#define SLC_EXPORT 1
#define SLC_RVALUE 2
static int slc_mode = SLC_EXPORT;
void
slc_init()
{
register struct spc *spcp;
localchars = 1;
for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
spcp->val = 0;
spcp->valp = 0;
spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
}
#define initfunc(func, flags) { \
spcp = &spc_data[func]; \
if (spcp->valp = tcval(func)) { \
spcp->val = *spcp->valp; \
spcp->mylevel = SLC_VARIABLE|flags; \
} else { \
spcp->val = 0; \
spcp->mylevel = SLC_DEFAULT; \
} \
}
initfunc(SLC_SYNCH, 0);
/* No BRK */
initfunc(SLC_AO, 0);
initfunc(SLC_AYT, 0);
/* No EOR */
initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
initfunc(SLC_EOF, 0);
#ifndef SYSV_TERMIO
initfunc(SLC_SUSP, SLC_FLUSHIN);
#endif
initfunc(SLC_EC, 0);
initfunc(SLC_EL, 0);
#ifndef SYSV_TERMIO
initfunc(SLC_EW, 0);
initfunc(SLC_RP, 0);
initfunc(SLC_LNEXT, 0);
#endif
initfunc(SLC_XON, 0);
initfunc(SLC_XOFF, 0);
#ifdef SYSV_TERMIO
spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
#endif
initfunc(SLC_FORW1, 0);
#ifdef USE_TERMIO
initfunc(SLC_FORW2, 0);
/* No FORW2 */
#endif
initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
#undef initfunc
if (slc_mode == SLC_EXPORT)
slc_export();
else
slc_import(1);
}
void
slcstate()
{
printf("Special characters are %s values\n",
slc_mode == SLC_IMPORT ? "remote default" :
slc_mode == SLC_EXPORT ? "local" :
"remote");
}
void
slc_mode_export()
{
slc_mode = SLC_EXPORT;
if (my_state_is_will(TELOPT_LINEMODE))
slc_export();
}
void
slc_mode_import(def)
int def;
{
slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
if (my_state_is_will(TELOPT_LINEMODE))
slc_import(def);
}
unsigned char slc_import_val[] = {
IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
};
unsigned char slc_import_def[] = {
IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
};
void
slc_import(def)
int def;
{
if (NETROOM() > sizeof(slc_import_val)) {
if (def) {
ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
} else {
ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
}
}
/*@*/ else printf("slc_import: not enough room\n");
}
void
slc_export()
{
register struct spc *spcp;
TerminalDefaultChars();
slc_start_reply();
for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
if (spcp->mylevel != SLC_NOSUPPORT) {
if (spcp->val == (cc_t)(_POSIX_VDISABLE))
spcp->flags = SLC_NOSUPPORT;
else
spcp->flags = spcp->mylevel;
if (spcp->valp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -