mirror of
https://git.savannah.gnu.org/git/inetutils.git
synced 2026-01-12 00:19:39 +08:00
428 lines
10 KiB
C
428 lines
10 KiB
C
/*
|
||
Copyright (C) 1995-2025 Free Software Foundation, Inc.
|
||
|
||
This file is part of GNU Inetutils.
|
||
|
||
GNU Inetutils is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or (at
|
||
your option) any later version.
|
||
|
||
GNU Inetutils is distributed in the hope that it will be useful, but
|
||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see `http://www.gnu.org/licenses/'. */
|
||
|
||
/*
|
||
* 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. 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.
|
||
*/
|
||
|
||
#include <config.h>
|
||
|
||
#include <sys/types.h>
|
||
|
||
#include <stdlib.h>
|
||
#ifdef HAVE_LOCALE_H
|
||
# include <locale.h>
|
||
#endif
|
||
|
||
#include "ring.h"
|
||
#include "defines.h"
|
||
#include "externs.h"
|
||
|
||
#include <progname.h>
|
||
#include <error.h>
|
||
#include <argp.h>
|
||
#include <attribute.h>
|
||
#include <libinetutils.h>
|
||
|
||
#include <arpa/telnet.h>
|
||
|
||
#ifdef AUTHENTICATION
|
||
# include <libtelnet/auth.h>
|
||
#endif
|
||
#ifdef ENCRYPTION
|
||
# include <libtelnet/encrypt.h>
|
||
#endif
|
||
|
||
/* These values need to be the same as defined in libtelnet/kerberos5.c */
|
||
/* Either define them in both places, or put in some common header file. */
|
||
#define OPTS_FORWARD_CREDS 0x00000002
|
||
#define OPTS_FORWARDABLE_CREDS 0x00000001
|
||
|
||
#if 0
|
||
# define FORWARD
|
||
#endif
|
||
|
||
/*
|
||
* Initialize variables.
|
||
*/
|
||
void
|
||
tninit (void)
|
||
{
|
||
init_terminal ();
|
||
|
||
init_network ();
|
||
|
||
init_telnet ();
|
||
|
||
init_sys ();
|
||
|
||
#if defined TN3270
|
||
init_3270 ();
|
||
#endif
|
||
}
|
||
|
||
int family = 0;
|
||
char *user, *srcaddr;
|
||
#ifdef FORWARD
|
||
extern int forward_flags;
|
||
#endif /* FORWARD */
|
||
|
||
enum
|
||
{
|
||
OPTION_NOASYNCH = 256,
|
||
OPTION_NOASYNCTTY,
|
||
OPTION_NOASYNCNET
|
||
};
|
||
|
||
#if defined KERBEROS || defined SHISHI
|
||
extern char *dest_realm;
|
||
#endif
|
||
|
||
static struct argp_option argp_options[] = {
|
||
#define GRID 10
|
||
{NULL, 0, NULL, 0,
|
||
"General options:", GRID},
|
||
|
||
{"ipv4", '4', NULL, 0,
|
||
"use only IPv4", GRID + 1},
|
||
{"ipv6", '6', NULL, 0,
|
||
"use only IPv6", GRID + 1},
|
||
/* FIXME: Called "8bit" in r* utils */
|
||
{"binary", '8', NULL, 0,
|
||
"use an 8-bit data transmission", GRID + 1},
|
||
{"bind", 'b', "ADDRESS", 0,
|
||
"bind to specific local ADDRESS", GRID + 1},
|
||
{"login", 'a', NULL, 0,
|
||
"attempt automatic login", GRID + 1},
|
||
{"no-rc", 'c', NULL, 0,
|
||
"do not read the user's .telnetrc file", GRID + 1},
|
||
{"debug", 'd', NULL, 0,
|
||
"turn on debugging", GRID + 1},
|
||
{"escape", 'e', "CHAR", 0,
|
||
"use CHAR as an escape character", GRID + 1},
|
||
{"no-escape", 'E', NULL, 0,
|
||
"use no escape character", GRID + 1},
|
||
{"no-login", 'K', NULL, 0,
|
||
"do not automatically login to the remote system", GRID + 1},
|
||
{"user", 'l', "USER", 0,
|
||
"attempt automatic login as USER", GRID + 1},
|
||
{"binary-output", 'L', NULL, 0, /* FIXME: Why L?? */
|
||
"use an 8-bit data transmission for output only", GRID + 1},
|
||
{"trace", 'n', "FILE", 0,
|
||
"record trace information into FILE", GRID + 1},
|
||
{"rlogin", 'r', NULL, 0,
|
||
"use a user-interface similar to rlogin", GRID + 1},
|
||
#undef GRID
|
||
|
||
#ifdef ENCRYPTION
|
||
# define GRID 20
|
||
{NULL, 0, NULL, 0,
|
||
"Encryption control:", GRID},
|
||
{"encrypt", 'x', NULL, 0,
|
||
"encrypt the data stream, if possible", GRID + 1},
|
||
# undef GRID
|
||
#endif
|
||
|
||
#ifdef AUTHENTICATION
|
||
# define GRID 30
|
||
{NULL, 0, NULL, 0,
|
||
"Authentication and Kerberos options:", GRID},
|
||
{"disable-auth", 'X', "ATYPE", 0,
|
||
"disable type ATYPE authentication", GRID + 1},
|
||
# if defined KERBEROS || defined SHISHI
|
||
{"realm", 'k', "REALM", 0,
|
||
"obtain tickets for the remote host in REALM "
|
||
"instead of the remote host's realm", GRID + 1},
|
||
# endif
|
||
# if defined KRB5 && defined FORWARD
|
||
{"fwd-credentials", 'f', NULL, 0,
|
||
"allow the local credentials to be forwarded", GRID + 1},
|
||
{NULL, 'F', NULL, 0,
|
||
"forward a forwardable copy of the local credentials "
|
||
"to the remote system", GRID + 1},
|
||
# endif
|
||
# undef GRID
|
||
#endif
|
||
|
||
#if defined TN3270 && (defined unix || defined __unix || defined __unix__)
|
||
# define GRID 40
|
||
{NULL, 0, NULL, 0,
|
||
"TN3270 support:", GRID},
|
||
/* FIXME: Do we need it? */
|
||
{"transcom", 't', "ARG", 0, "", GRID + 1},
|
||
{"noasynch", OPTION_NOASYNCH, NULL, 0, "", GRID + 1},
|
||
{"noasynctty", OPTION_NOASYNCTTY, NULL, 0, "", GRID + 1},
|
||
{"noasyncnet", OPTION_NOASYNCNET, NULL, 0, "", GRID + 1},
|
||
# undef GRID
|
||
#endif /* TN3270 && (unix || __unix || __unix__) */
|
||
{NULL, 0, NULL, 0, NULL, 0}
|
||
};
|
||
|
||
static error_t
|
||
parse_opt (int key, char *arg, struct argp_state *state MAYBE_UNUSED)
|
||
{
|
||
switch (key)
|
||
{
|
||
case '4':
|
||
family = 4;
|
||
break;
|
||
|
||
case '6':
|
||
family = 6;
|
||
break;
|
||
|
||
case '8':
|
||
eight = 3; /* binary output and input */
|
||
break;
|
||
|
||
case 'E':
|
||
rlogin = escape = _POSIX_VDISABLE;
|
||
break;
|
||
|
||
case 'K':
|
||
#ifdef AUTHENTICATION
|
||
autologin = 0;
|
||
#endif
|
||
break;
|
||
|
||
case 'L':
|
||
eight |= 2; /* binary output only */
|
||
break;
|
||
|
||
#ifdef AUTHENTICATION
|
||
case 'X':
|
||
auth_disable_name (arg);
|
||
break;
|
||
#endif
|
||
|
||
case 'a':
|
||
autologin = 1;
|
||
break;
|
||
|
||
case 'c':
|
||
skiprc = 1;
|
||
break;
|
||
|
||
case 'd':
|
||
debug = 1;
|
||
break;
|
||
|
||
case 'e':
|
||
set_escape_char (arg);
|
||
break;
|
||
|
||
#if defined AUTHENTICATION && defined KRB5 && defined FORWARD
|
||
case 'f':
|
||
if (forward_flags & OPTS_FORWARD_CREDS)
|
||
argp_error (state, "Only one of -f and -F allowed.", prompt);
|
||
forward_flags |= OPTS_FORWARD_CREDS;
|
||
break;
|
||
|
||
case 'F':
|
||
if (forward_flags & OPTS_FORWARD_CREDS)
|
||
argp_error (state, "Only one of -f and -F allowed");
|
||
forward_flags |= OPTS_FORWARD_CREDS;
|
||
forward_flags |= OPTS_FORWARDABLE_CREDS;
|
||
break;
|
||
#endif
|
||
|
||
#if defined AUTHENTICATION && \
|
||
( defined KERBEROS || defined SHISHI )
|
||
case 'k':
|
||
dest_realm = arg;
|
||
break;
|
||
#endif
|
||
|
||
case 'l':
|
||
autologin = 1;
|
||
user = arg;
|
||
break;
|
||
|
||
case 'n':
|
||
SetNetTrace (arg);
|
||
break;
|
||
|
||
case 'r':
|
||
rlogin = '~';
|
||
break;
|
||
|
||
#if defined TN3270 && (defined unix || defined __unix || defined __unix__)
|
||
case 't':
|
||
/* FIXME: Buffer!!! */
|
||
transcom = tline;
|
||
strcpy (transcom, arg);
|
||
break;
|
||
|
||
case OPTION_NOASYNCH:
|
||
noasynchtty = noasynchtty = 1;
|
||
break;
|
||
|
||
case OPTION_NOASYNCTTY:
|
||
noasynchtty = 1;
|
||
break;
|
||
|
||
case OPTION_NOASYNCNET:
|
||
noasynchnet = 1;
|
||
break;
|
||
#endif /* TN3270 && (unix || __unix || __unix__) */
|
||
|
||
#ifdef ENCRYPTION
|
||
case 'x':
|
||
encrypt_auto (1);
|
||
decrypt_auto (1);
|
||
break;
|
||
#endif
|
||
|
||
case 'b':
|
||
srcaddr = arg;
|
||
break;
|
||
|
||
default:
|
||
return ARGP_ERR_UNKNOWN;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
const char args_doc[] = "[HOST [PORT]]";
|
||
const char doc[] = "Login to remote system HOST "
|
||
"(optionally, on service port PORT)";
|
||
static struct argp argp =
|
||
{ argp_options, parse_opt, args_doc, doc, NULL, NULL, NULL };
|
||
|
||
|
||
|
||
/*
|
||
* main. Parse arguments, invoke the protocol or command parser.
|
||
*/
|
||
int
|
||
main (int argc, char *argv[])
|
||
{
|
||
int index;
|
||
|
||
set_program_name (argv[0]);
|
||
|
||
#ifdef HAVE_SETLOCALE
|
||
setlocale (LC_ALL, "");
|
||
#endif
|
||
|
||
tninit (); /* Clear out things */
|
||
#if defined CRAY && !defined __STDC__
|
||
_setlist_init (); /* Work around compiler bug */
|
||
#endif
|
||
|
||
TerminalSaveState ();
|
||
|
||
if ((prompt = strrchr (argv[0], '/')))
|
||
++prompt;
|
||
else
|
||
prompt = argv[0];
|
||
|
||
user = NULL;
|
||
|
||
rlogin = (strncmp (prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
|
||
autologin = -1;
|
||
|
||
/* Parse command line */
|
||
iu_argp_init ("telnet", default_program_authors);
|
||
argp_parse (&argp, argc, argv, 0, &index, NULL);
|
||
|
||
if (autologin == -1)
|
||
autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
|
||
|
||
argc -= index;
|
||
argv += index;
|
||
|
||
if (argc)
|
||
{
|
||
/* The command line contains at least one argument.
|
||
*/
|
||
char *args[10], **argp = args;
|
||
|
||
if (argc > 2)
|
||
error (EXIT_FAILURE, 0, "too many arguments");
|
||
*argp++ = prompt;
|
||
if (user)
|
||
{
|
||
*argp++ = "-l";
|
||
*argp++ = user;
|
||
}
|
||
if (srcaddr)
|
||
{
|
||
*argp++ = "-b";
|
||
*argp++ = srcaddr;
|
||
}
|
||
if (family == 4)
|
||
*argp++ = "-4";
|
||
else if (family == 6)
|
||
*argp++ = "-6";
|
||
|
||
*argp++ = argv[0]; /* host */
|
||
if (argc > 1)
|
||
*argp++ = argv[1]; /* port */
|
||
*argp = 0;
|
||
|
||
if (setjmp (toplevel) != 0)
|
||
Exit (0);
|
||
if (tn (argp - args, args) == 1) /* Returns only on error. */
|
||
return (0);
|
||
else
|
||
return (1);
|
||
/* NOT REACHED */
|
||
}
|
||
|
||
/* Built-in parser loop; sub-commands jump to `toplevel' mark. */
|
||
setjmp (toplevel);
|
||
for (;;)
|
||
{
|
||
#ifdef TN3270
|
||
if (shell_active)
|
||
shell_continue ();
|
||
else
|
||
#endif
|
||
command (1, 0, 0);
|
||
}
|
||
/* NOT REACHED */
|
||
}
|