/* * 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. */ #ifndef lint static char sccsid[] = "@(#)commands.c 5.5 (Berkeley) 3/22/91"; #endif /* not lint */ #if defined(unix) #include #ifdef CRAY #include #endif #include #else #include #endif /* defined(unix) */ #include #include #ifdef CRAY #include #endif /* CRAY */ #include #include #include #include #include #include #include #include "general.h" #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" #ifndef CRAY #include # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) # include # endif /* vax */ #endif /* CRAY */ #include #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) */ }; extern 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 what; /* what we are sending this time */ 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, what); printoption("SENT", IAC, what); } } return (count == success); } static int send_esc() { NETADD(escape); return 1; } static int send_docmd(name) char *name; { void send_do(); return(send_tncmd(send_do, "do", name)); } static int send_dontcmd(name) char *name; { void send_dont(); return(send_tncmd(send_dont, "dont", name)); } static int send_willcmd(name) char *name; { void send_will(); return(send_tncmd(send_will, "will", name)); } static int send_wontcmd(name) char *name; { void send_wont(); return(send_tncmd(send_wont, "wont", name)); } int send_tncmd(func, cmd, name) void (*func)(); char *cmd, *name; { char **cpp; extern char *telopts[]; if (isprefix(name, "help") || isprefix(name, "?")) { register int col, len; printf("Usage: send %s