📄 commands.cc
字号:
/* * Copyright (c) 1988, 1990 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. *//* * From: @(#)commands.c 5.5 (Berkeley) 3/22/91 */char cmd_rcsid[] = "$Id: commands.cc,v 1.34 2000/07/23 04:16:24 dholland Exp $";#include <string.h>#include <sys/param.h>#include <sys/file.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h>#ifdef CRAY#include <fcntl.h>#endif /* CRAY */#include <sys/wait.h>#include <signal.h>#include <netdb.h>#include <ctype.h>#include <pwd.h>#include <stdarg.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <arpa/inet.h>#include <arpa/telnet.h>#include "ring.h"#include "externs.h"#include "defines.h"#include "types.h"#include "genget.h"#include "environ.h"#include "proto.h"#include "ptrarray.h"#include "netlink.h"/* In Linux, this is an enum */#if defined(__linux__) || defined(IPPROTO_IP)#define HAS_IPPROTO_IP#endif#ifndef CRAY#if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)#include <machine/endian.h>#endif /* vax */#endif /* CRAY */#define HELPINDENT ((int) sizeof ("connect"))#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN 64#endif MAXHOSTNAMELEN#if defined(HAS_IPPROTO_IP) && defined(IP_TOS)int tos = -1;#endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */static unsigned long sourceroute(char *arg, char **cpp, int *lenp);char *hostname;static char _hostname[MAXHOSTNAMELEN];//typedef int (*intrtn_t)(int argc, const char *argv[]);class command_entry;typedef ptrarray<command_entry> command_table;static int process_command(command_table *tab, int argc, const char **argv);class command_entry { protected: const char *name; /* command name */ const char *help; /* help string (NULL for no help) */ int nargs; union { /* routine which executes command */ command_table *subhandler; int (*handlern)(int, const char **); int (*handler0)(void); int (*handler1)(const char *); int (*handler2)(const char *, const char *); }; public: command_entry(const char *n, const char *e, int (*h)(int, const char **)) { name = n; help = e; nargs = -1; handlern = h; } command_entry(const char *n, const char *e, int (*h)(void)) { name = n; help = e; nargs = 0; handler0 = h; } command_entry(const char *n, const char *e, int (*h)(const char *)) { name = n; help = e; nargs = 1; handler1 = h; } command_entry(const char *n, const char *e, int (*h)(const char *, const char *)) { name = n; help = e; nargs = 2; handler2 = h; } command_entry(const char *n, const char *e, command_table *sub) { name = n; help = e; nargs = -2; subhandler = sub; } int call(int argc, const char *argv[]) { assert(argc>=1); if (nargs>=0 && argc!=nargs+1) { fprintf(stderr, "Wrong number of arguments for command.\n"); fprintf(stderr, "Try %s ? for help\n", argv[0]); return 0; /* is this right? */ } if (nargs==-2) { if (argc<2) { fprintf(stderr, "`%s' requires a subcommand.\n", argv[0]); fprintf(stderr, "Try %s ? for help\n", argv[0]); return 0; /* is this right? */ } return process_command(subhandler, argc-1, argv+1); } else if (nargs==-1) return handlern(argc, argv); else if (nargs==0) return handler0(); else if (nargs==1) return handler1(argv[1]); else if (nargs==2) return handler2(argv[1], argv[2]); return 0; } void describe() { if (help) printf("%-*s\t%s\n", HELPINDENT, name, help); } void gethelp() { if (help) printf("%s\n", help); else printf("No help available\n"); } const char *getname() const { return name; }};static char line[256];static char saveline[256];static int margc;static const char *margv[20];static void makeargv(void) { register char *cp, *cp2, c; register const 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)!=0) { 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 int special(const char *s) { 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 const char *control(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 { const char *name; /* How user refers to it (case independent) */ const char *help; /* Help information (0 ==> no help) */ int needconnect; /* Need to be connected */ int narg; /* Number of arguments */ int (*handler)(const char *, const char *); /* 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(const char *, const char *);static int send_help(const char *, const char *);static int send_docmd(const char *, const char *);static int send_dontcmd(const char *, const char *);static int send_willcmd(const char *, const char *);static int send_wontcmd(const char *, const char *);extern int send_do(int, int);extern int send_dont(int, int);extern int send_will(int, int);extern int send_wont(int, int);static int dosynch1(const char *, const char *) { return dosynch(); }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, dosynch1, 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, 0, 0, 0, 0, 0, 0 }};#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ sizeof(struct sendlist)))static int sendcmd(int argc, const 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 (s == AMBIGUOUS) { 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(NULL, NULL); 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 (netoring.empty_count() < 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"); 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(const char *, const char *) { NETADD(escapechar); return 1;}static int send_docmd(const char *name, const char *) { return send_tncmd(send_do, "do", name);}static int send_dontcmd(const char *name, const char *) { return(send_tncmd(send_dont, "dont", name));}static int send_willcmd(const char *name, const char *) { return(send_tncmd(send_will, "will", name));}static int send_wontcmd(const char *name, const char *) { return(send_tncmd(send_wont, "wont", name));}int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) { char **cpp; extern char *telopts[]; if (isprefix(name, "help") || isprefix(name, "?")) { register int col, len; printf("Usage: send %s <option>\n", cmd); printf("Valid options are:\n\t"); col = 8; for (cpp = telopts; *cpp; cpp++) { len = strlen(*cpp) + 1; if (col + len > 65) { printf("\n\t"); col = 8; } printf(" %s", *cpp); col += len; } printf("\n"); return 0; } cpp = genget(name, telopts, sizeof(char *)); if (cpp == AMBIGUOUS) { fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", name, cmd); return 0; } if (cpp == 0) { fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", name, cmd); return 0; } if (!connected) { printf("?Need to be connected first.\n"); return 0; } (*func)(cpp - telopts, 1); return 1;}static int send_help(const char *, const char *) { 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(int) { donelclchars = 1; return 1;}static int togdebug(int) { return nlink.setdebug(debug);}static int togcrlf(int) { 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -