📄 commands.c
字号:
/*
* Copyright (c) 1988, 1990, 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.
*/
#ifndef lint
static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
#endif /* not lint */
#if defined(unix)
#include <sys/param.h>
#if defined(CRAY) || defined(sysV88)
#include <sys/types.h>
#endif
#include <sys/file.h>
#else
#include <sys/types.h>
#endif /* defined(unix) */
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef CRAY
#include <fcntl.h>
#endif /* CRAY */
#include <signal.h>
#include <netdb.h>
#include <ctype.h>
#include <pwd.h>
#include <varargs.h>
#include <errno.h>
#include <arpa/telnet.h>
#include "general.h"
#include "ring.h"
#include "externs.h"
#include "defines.h"
#include "types.h"
#if !defined(CRAY) && !defined(sysV88)
#include <netinet/in_systm.h>
# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
# include <machine/endian.h>
# endif /* vax */
#endif /* !defined(CRAY) && !defined(sysV88) */
#include <netinet/ip.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif MAXHOSTNAMELEN
#if defined(IPPROTO_IP) && defined(IP_TOS)
int tos = -1;
#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
char *hostname;
static char _hostname[MAXHOSTNAMELEN];
extern char *getenv();
extern int isprefix();
extern char **genget();
extern int Ambiguous();
static call();
typedef struct {
char *name; /* command name */
char *help; /* help string (NULL for no help) */
int (*handler)(); /* routine which executes command */
int needconnect; /* Do we need to be connected to execute? */
} Command;
static char line[256];
static char saveline[256];
static int margc;
static char *margv[20];
static void
makeargv()
{
register char *cp, *cp2, c;
register char **argp = margv;
margc = 0;
cp = line;
if (*cp == '!') { /* Special case shell escape */
strcpy(saveline, line); /* save for shell command */
*argp++ = "!"; /* No room in string to get this */
margc++;
cp++;
}
while (c = *cp) {
register int inquote = 0;
while (isspace(c))
c = *++cp;
if (c == '\0')
break;
*argp++ = cp;
margc += 1;
for (cp2 = cp; c != '\0'; c = *++cp) {
if (inquote) {
if (c == inquote) {
inquote = 0;
continue;
}
} else {
if (c == '\\') {
if ((c = *++cp) == '\0')
break;
} else if (c == '"') {
inquote = '"';
continue;
} else if (c == '\'') {
inquote = '\'';
continue;
} else if (isspace(c))
break;
}
*cp2++ = c;
}
*cp2 = '\0';
if (c == '\0')
break;
cp++;
}
*argp++ = 0;
}
/*
* Make a character string into a number.
*
* Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
*/
static
special(s)
register char *s;
{
register char c;
char b;
switch (*s) {
case '^':
b = *++s;
if (b == '?') {
c = b | 0x40; /* DEL */
} else {
c = b & 0x1f;
}
break;
default:
c = *s;
break;
}
return c;
}
/*
* Construct a control character sequence
* for a special character.
*/
static char *
control(c)
register cc_t c;
{
static char buf[5];
/*
* The only way I could get the Sun 3.5 compiler
* to shut up about
* if ((unsigned int)c >= 0x80)
* was to assign "c" to an unsigned int variable...
* Arggg....
*/
register unsigned int uic = (unsigned int)c;
if (uic == 0x7f)
return ("^?");
if (c == (cc_t)_POSIX_VDISABLE) {
return "off";
}
if (uic >= 0x80) {
buf[0] = '\\';
buf[1] = ((c>>6)&07) + '0';
buf[2] = ((c>>3)&07) + '0';
buf[3] = (c&07) + '0';
buf[4] = 0;
} else if (uic >= 0x20) {
buf[0] = c;
buf[1] = 0;
} else {
buf[0] = '^';
buf[1] = '@'+c;
buf[2] = 0;
}
return (buf);
}
/*
* The following are data structures and routines for
* the "send" command.
*
*/
struct sendlist {
char *name; /* How user refers to it (case independent) */
char *help; /* Help information (0 ==> no help) */
int needconnect; /* Need to be connected */
int narg; /* Number of arguments */
int (*handler)(); /* Routine to perform (for special ops) */
int nbyte; /* Number of bytes to send this command */
int what; /* Character to be sent (<0 ==> special) */
};
static int
send_esc P((void)),
send_help P((void)),
send_docmd P((char *)),
send_dontcmd P((char *)),
send_willcmd P((char *)),
send_wontcmd P((char *));
static struct sendlist Sendlist[] = {
{ "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
{ "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
{ "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
{ "break", 0, 1, 0, 0, 2, BREAK },
{ "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
{ "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
{ "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
{ "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
{ "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
{ "intp", 0, 1, 0, 0, 2, IP },
{ "interrupt", 0, 1, 0, 0, 2, IP },
{ "intr", 0, 1, 0, 0, 2, IP },
{ "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
{ "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
{ "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
{ "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
{ "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
{ "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
{ "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
{ "?", "Display send options", 0, 0, send_help, 0, 0 },
{ "help", 0, 0, 0, send_help, 0, 0 },
{ "do", 0, 0, 1, send_docmd, 3, 0 },
{ "dont", 0, 0, 1, send_dontcmd, 3, 0 },
{ "will", 0, 0, 1, send_willcmd, 3, 0 },
{ "wont", 0, 0, 1, send_wontcmd, 3, 0 },
{ 0 }
};
#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
sizeof(struct sendlist)))
static int
sendcmd(argc, argv)
int argc;
char **argv;
{
int count; /* how many bytes we are going to need to send */
int i;
int question = 0; /* was at least one argument a question */
struct sendlist *s; /* pointer to current command */
int success = 0;
int needconnect = 0;
if (argc < 2) {
printf("need at least one argument for 'send' command\n");
printf("'send ?' for help\n");
return 0;
}
/*
* First, validate all the send arguments.
* In addition, we see how much space we are going to need, and
* whether or not we will be doing a "SYNCH" operation (which
* flushes the network queue).
*/
count = 0;
for (i = 1; i < argc; i++) {
s = GETSEND(argv[i]);
if (s == 0) {
printf("Unknown send argument '%s'\n'send ?' for help.\n",
argv[i]);
return 0;
} else if (Ambiguous(s)) {
printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
argv[i]);
return 0;
}
if (i + s->narg >= argc) {
fprintf(stderr,
"Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n",
s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
return 0;
}
count += s->nbyte;
if (s->handler == send_help) {
send_help();
return 0;
}
i += s->narg;
needconnect += s->needconnect;
}
if (!connected && needconnect) {
printf("?Need to be connected first.\n");
printf("'send ?' for help\n");
return 0;
}
/* Now, do we have enough room? */
if (NETROOM() < count) {
printf("There is not enough room in the buffer TO the network\n");
printf("to process your request. Nothing will be done.\n");
printf("('send synch' will throw away most data in the network\n");
printf("buffer, if this might help.)\n");
return 0;
}
/* OK, they are all OK, now go through again and actually send */
count = 0;
for (i = 1; i < argc; i++) {
if ((s = GETSEND(argv[i])) == 0) {
fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
(void) quit();
/*NOTREACHED*/
}
if (s->handler) {
count++;
success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
(s->narg > 1) ? argv[i+2] : 0);
i += s->narg;
} else {
NET2ADD(IAC, s->what);
printoption("SENT", IAC, s->what);
}
}
return (count == success);
}
static int
send_esc()
{
NETADD(escape);
return 1;
}
static int
send_docmd(name)
char *name;
{
return(send_tncmd(send_do, "do", name));
}
static int
send_dontcmd(name)
char *name;
{
return(send_tncmd(send_dont, "dont", name));
}
static int
send_willcmd(name)
char *name;
{
return(send_tncmd(send_will, "will", name));
}
static int
send_wontcmd(name)
char *name;
{
return(send_tncmd(send_wont, "wont", name));
}
int
send_tncmd(func, cmd, name)
void (*func)();
char *cmd, *name;
{
char **cpp;
extern char *telopts[];
register int val = 0;
if (isprefix(name, "help") || isprefix(name, "?")) {
register int col, len;
printf("Usage: send %s <value|option>\n", cmd);
printf("\"value\" must be from 0 to 255\n");
printf("Valid options are:\n\t");
col = 8;
for (cpp = telopts; *cpp; cpp++) {
len = strlen(*cpp) + 3;
if (col + len > 65) {
printf("\n\t");
col = 8;
}
printf(" \"%s\"", *cpp);
col += len;
}
printf("\n");
return 0;
}
cpp = (char **)genget(name, telopts, sizeof(char *));
if (Ambiguous(cpp)) {
fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
name, cmd);
return 0;
}
if (cpp) {
val = cpp - telopts;
} else {
register char *cp = name;
while (*cp >= '0' && *cp <= '9') {
val *= 10;
val += *cp - '0';
cp++;
}
if (*cp != 0) {
fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
name, cmd);
return 0;
} else if (val < 0 || val > 255) {
fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
name, cmd);
return 0;
}
}
if (!connected) {
printf("?Need to be connected first.\n");
return 0;
}
(*func)(val, 1);
return 1;
}
static int
send_help()
{
struct sendlist *s; /* pointer to current command */
for (s = Sendlist; s->name; s++) {
if (s->help)
printf("%-15s %s\n", s->name, s->help);
}
return(0);
}
/*
* The following are the routines and data structures referred
* to by the arguments to the "toggle" command.
*/
static int
lclchars()
{
donelclchars = 1;
return 1;
}
static int
togdebug()
{
#ifndef NOT43
if (net > 0 &&
(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
perror("setsockopt (SO_DEBUG)");
}
#else /* NOT43 */
if (debug) {
if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
perror("setsockopt (SO_DEBUG)");
} else
printf("Cannot turn off socket debugging\n");
#endif /* NOT43 */
return 1;
}
static int
togcrlf()
{
if (crlf) {
printf("Will send carriage returns as telnet <CR><LF>.\n");
} else {
printf("Will send carriage returns as telnet <CR><NUL>.\n");
}
return 1;
}
int binmode;
static int
togbinary(val)
int val;
{
donebinarytoggle = 1;
if (val >= 0) {
binmode = val;
} else {
if (my_want_state_is_will(TELOPT_BINARY) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -