📄 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. */#ifdef SHOW_SCCIDSstatic char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";#endif#include "config.h"#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_FILE_H#include <sys/file.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <sys/socket.h>#include <netinet/in.h>#ifdef HAVE_SYS_FCNTL_H#include <sys/fcntl.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#include <stdio.h>#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <signal.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"#ifdef HAVE_MACHINE_ENDIAN_H#include <machine/endian.h>#endif#include <netinet/ip.h>#define DONT_NEED_SIGBLOCK#define DONT_NEED_SIGUNBLOCK#define DONT_NEED_SIGPAUSE#define DONT_NEED_SIGPENDING#include "sigfix.h"#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN 64#endif #if defined(IPPROTO_IP) && defined(IP_TOS)int tos = -1;#endifchar *hostname;static char _hostname[MAXHOSTNAMELEN];extern int isprefix();extern char **genget();extern int Ambiguous();extern void herror();static int 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];void cmdrc P((char *, char *));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((unsigned char)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((unsigned char)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 char special(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(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)))/*VARARGS*/static int bye(int argc, char *argv[]) { extern int resettermname; if (connected) { (void) shutdown(net, 2); printf("Connection closed.\n"); (void) NetClose(net); connected = 0; resettermname = 1; /* reset options */ tninit();#ifdef TN3270 SetIn3270(); /* Get out of 3270 mode */#endif /* defined(TN3270) */ } if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { longjmp(toplevel, 1); /* NOTREACHED */ } return 1; /* Keep lint, etc., happy */}int quit() { call(bye, "bye", "fromquit", 0); Exit(0); /*NOTREACHED*/ return 0;}int logout() { send_do(TELOPT_LOGOUT, 1); netflush(); return 1;}static int sendcmd(int argc, char **argv) { int count; /* how many bytes we are going to need to send */ int i; 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_tncmd(void (*func)(), char *cmd, char *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_docmd(char *name) { return(send_tncmd(send_do, "do", name));}static int send_dontcmd(char *name) { return(send_tncmd(send_dont, "dont", name));}static int send_willcmd(char *name) { return(send_tncmd(send_will, "will", name));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -