⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rlogin.c

📁 压缩包中包含LINUX下多个命令的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983, 1990, 1993, 2002 *	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. * 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. *//* * rlogin - remote login */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#include <sys/ioctl.h>#ifdef HAVE_SYS_STREAM_H#include <sys/stream.h>#endif#ifdef HAVE_SYS_TTY_H#include <sys/tty.h>#endif#ifdef HAVE_SYS_PTYVAR_H#include <sys/ptyvar.h>#endif#ifdef HAVE_SYS_SOCKIO_H#include <sys/sockio.h>#endif#include <netinet/in.h>#ifdef HAVE_NETINET_IN_SYSTM_H#include <netinet/in_systm.h>#endif#ifdef HAVE_NETINET_IP_H#include <netinet/ip.h>#endif#include <err.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <netdb.h>#include <pwd.h>#include <setjmp.h>#include <termios.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#ifdef KERBEROS#include <kerberosIV/des.h>#include <kerberosIV/krb.h>CREDENTIALS cred;Key_schedule schedule;int use_kerberos = 1, doencrypt;char dst_realm_buf[REALM_SZ], *dest_realm = NULL;#endif/*  The TIOCPKT_* macros may not be implemented in the pty driver.  Defining them here allows the program to be compiled.  */#ifndef TIOCPKT# define TIOCPKT                 _IOW('t', 112, int)# define TIOCPKT_FLUSHWRITE      0x02# define TIOCPKT_NOSTOP          0x10# define TIOCPKT_DOSTOP          0x20#endif /*TIOCPKT*//* The server sends us a TIOCPKT_WINDOW notification when it starts up.   The value for this (0x80) can not overlap the kernel defined TIOCPKT_xxx   values.  */#ifndef TIOCPKT_WINDOW#define	TIOCPKT_WINDOW	0x80#endif/* Concession to Sun.  */#ifndef SIGUSR1#define	SIGUSR1	30#endif#ifndef	_POSIX_VDISABLE# ifdef VDISABLE#  define _POSIX_VDISABLE VDISABLE# else#  define _POSIX_VDISABLE ((cc_t)'\377')# endif#endif/* Returned by speed() when the specified fd is not associated with a   terminal.  */#define SPEED_NOTATTY	(-1)int eight, rem;int noescape;u_char escapechar = '~';#ifdef OLDSUNstruct winsize{  unsigned short ws_row;    /* Rows, in characters.  */  unsigned short ws_col;    /* Columns , in characters.  */  unsigned short ws_xpixel; /* Horizontal size, pixels.  */  unsigned short ws_ypixel; /* Vertical size. pixels.  */};int   get_window_size __P ((int, struct winsize *));#else# define	get_window_size(fd, wp)	ioctl (fd, TIOCGWINSZ, wp)#endifstruct	winsize winsize;void  catch_child __P ((int));void  copytochild __P ((int));void  doit        __P ((sigset_t *));void  done        __P ((int));void  echo        __P ((char));u_int getescape   __P ((char *));void  lostpeer    __P ((int));void  mode        __P ((int));void  msg         __P ((const char *));void  oob         __P ((int));int   reader      __P ((sigset_t *));void  sendwindow  __P ((void));void  setsignal   __P ((int));int   speed       __P ((int));unsigned int speed_translate __P ((unsigned int));void  sigwinch    __P ((int));void  stop        __P ((char));void  usage       __P ((int));void  writer      __P ((void));void  writeroob   __P ((int));#ifdef	KERBEROSvoid  warning    __P ((const char *, ...));#endifextern sig_t setsig __P ((int, sig_t));#ifdef KERBEROS#define	OPTIONS	"8EKde:k:l:xhV"#else#define	OPTIONS	"8EKde:l:hV"#endifstatic const char *short_options = OPTIONS;static struct option long_options [] ={  { "debug", no_argument, 0, 'd' },  { "user", required_argument, 0, 'l' },  { "escape", required_argument, 0, 'e' },  { "no-escape", no_argument, 0, 'E' },  { "8-bit", no_argument, 0, '8' },  { "kerberos", no_argument, 0, 'K' },#ifdef KERBEROS  { "realm", required_argument, 0, 'k' },  { "encrypt", no_argument, 0, 'x' },#endif  { "help", no_argument, 0, 'h' },  { "version", no_argument, 0, 'V' },  { NULL, 0, 0, 0}};intmain(int argc, char *argv[]){  struct passwd *pw;  struct servent *sp;  sigset_t smask;  uid_t uid;  int ch, dflag;  int term_speed;  char *host, *user, term[1024];#ifndef HAVE___PROGNAME  extern char *__progname;  __progname = argv[0];#endif  dflag = 0;  host = user = NULL;  /* Traditionnaly, if a symbolic link was made to the rlogin binary     rlogin --> hostname     hostname will be use as the name of the server to login too.  */  {    char *p = strrchr (argv[0], '/');    if (p)      ++p;    else      p = argv[0];    if (strcmp (p, "rlogin") != 0)      host = p;  }  while ((ch = getopt_long (argc, argv, short_options, long_options, NULL))	 != EOF)    {      switch (ch)	{	  /* 8-bit input Specifying this forces us to use RAW mode input from	     the user's terminal.  Also, in this mode we won't perform any	     local flow control.  */	case '8':	  eight = 1;	  break;	case 'E':	  noescape = 1;	  break;	case 'K':#ifdef KERBEROS	  use_kerberos = 0;#endif	  break;	  /* Turn on the debug option for the socket.  */	case 'd':	  dflag = 1;	  break;	  /* Specify an escape character, instead of the default tilde.  */	case 'e':	  noescape = 0;	  escapechar = getescape (optarg);	  break;#ifdef KERBEROS	case 'k':	  strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf);	  /* Make sure it's null termintated.  */	  dest_realm_buf[sizeof (dest_realm_buf) - 1] = '\0';	  dest_realm = dst_realm_buf;	  break;#endif	  /* Specify the server-user-name, instead of using the name of the	     person invoking us.  */	case 'l':	  user = optarg;	  break;#ifdef ENCRYPTION# ifdef KERBEROS	case 'x':	  doencrypt = 1;	  des_set_key (cred.session, schedule);	  break;# endif#endif	case 'V':          printf ("rlogin (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION);          exit (0);	case '?':	  usage (1);	  break;	case 'h':	default:	  usage (0);	}    }  if (optind < argc)    host = argv[optind++];  argc -= optind;  /* To many command line arguments or too few.  */  if (argc > 0 || !host)    usage (1);  /* We must be uid root to access rcmd().  */  if (geteuid ())    errx (1, "must be setuid root.\n");  /* Get the name of the user invoking us: the client-user-name.  */  if (!(pw = getpwuid (uid = getuid ())))    errx (1, "unknown user id.");  /* Accept user1@host format, though "-l user2" overrides user1 */  {    char *p = strchr (host, '@');    if (p)      {	*p = '\0';	if (!user && p > host)	  user = host;	host = p + 1;	if (*host == '\0')	  usage (1);      }    if (!user)      user = pw->pw_name;  }  sp = NULL;#ifdef KERBEROS  if (use_kerberos)    {      sp = getservbyname ((doencrypt ? "eklogin" : "klogin"), "tcp");      if (sp == NULL)	{	  use_kerberos = 0;	  warning ("can't get entry for %s/tcp service",		   doencrypt ? "eklogin" : "klogin");	}    }#endif  /* Get the port number for the rlogin service.  */  if (sp == NULL)    sp = getservbyname ("login", "tcp");  if (sp == NULL)    errx (1, "login/tcp: unknown service.");  /* Get the name of the terminal from the environment.  Also get the     terminal's spee.  Both the name and the spee are passed to the server     as the "cmd" argument of the rcmd() function.  This is something like     "vt100/9600".  */  term_speed = speed (0);  if (term_speed == SPEED_NOTATTY)    {      char *p;      snprintf (term, sizeof term, "%s",		((p = getenv ("TERM")) ? p : "network"));    }  else    {      char *p;      snprintf (term, sizeof term, "%s/%d",		((p = getenv ("TERM")) ? p : "network"), term_speed);    }  get_window_size (0, &winsize);  setsig (SIGPIPE, lostpeer);  /* Block SIGURG and SIGUSR1 signals.  This will be handled by the     parent and the child after the fork.  */  /* Will use SIGUSR1 for window size hack, so hold it off.  */  sigemptyset (&smask);  sigaddset (&smask, SIGURG);  sigaddset (&smask, SIGUSR1);  sigprocmask (SIG_SETMASK, &smask, &smask);  /*   * We set SIGURG and SIGUSR1 below so that an   * incoming signal will be held pending rather than being   * discarded. Note that these routines will be ready to get   * a signal by the time that they are unblocked below.   */  setsig (SIGURG, copytochild);  setsig (SIGUSR1, writeroob);#ifdef KERBEROS try_connect:  if (use_kerberos)    {      struct hostent *hp;      /* Fully qualify hostname (needed for krb_realmofhost).  */      hp = gethostbyname (host);      if (hp != NULL && !(host = strdup (hp->h_name)))	errx (1, "%s", strerror (ENOMEM));      rem = KSUCCESS;      errno = 0;      if (dest_realm == NULL)	dest_realm = krb_realmofhost (host);# ifdef ENCRYPTION      if (doencrypt)	rem = krcmd_mutual (&host, sp->s_port, user, term, 0,			    dest_realm, &cred, schedule);      else#endif /* CRYPT */	rem = krcmd (&host, sp->s_port, user, term, 0, dest_realm);      if (rem < 0)	{	  use_kerberos = 0;	  sp = getservbyname ("login", "tcp");	  if (sp == NULL)	    errx (1, "unknown service login/tcp.");	  if (errno == ECONNREFUSED)	    warning ("remote host doesn't support Kerberos");	  if (errno == ENOENT)	    warning ("can't provide Kerberos auth data");	  goto try_connect;	}    }  else    {# ifdef ENCRYPTION      if (doencrypt)	errx (1, "the -x flag requires Kerberos authentication.");#endif /* CRYPT */      rem = rcmd (&host, sp->s_port, pw->pw_name, user, term, 0);    }#else  rem = rcmd (&host, sp->s_port, pw->pw_name, user, term, 0);#endif /* KERBEROS */  if (rem < 0)    exit (1);  {    int one = 1;    if (dflag && setsockopt (rem, SOL_SOCKET, SO_DEBUG, (char *) &one,			     sizeof one) < 0)      warn ("setsockopt DEBUG (ignored)");  }#if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_LOWDELAY)  {    int one = IPTOS_LOWDELAY;    if (setsockopt (rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof (int)) < 0)      warn ("setsockopt TOS (ignored)");  }#endif  /* Now change to the real user ID.  We have to be set-user-ID root     to get the privileged port that rcmd () uses,  however we now want to     run as the real user who invoked us.  */  seteuid (uid);  setuid (uid);  doit (&smask);  /*NOTREACHED*/  return 0;}/* Some systems, like QNX/Neutrino , The constant B0, B50,.. maps straigth to   the actual speed, 0, 50, ..., where on other system like GNU/Linux   it maps to a const 0, 1, ... i.e the value are encoded.   cfgetispeed(), according to posix should return a constant value reprensenting the Baud.   So to be portable we have to the conversion ourselves.  *//* Some values are not not define by POSIX.  */#ifndef B7200#define B7200   B4800#endif#ifndef B14400#define B14400  B9600#endif#ifndef B19200# define B19200 B14400#endif#ifndef B28800#define B28800  B19200#endif#ifndef B38400# define B38400 B28800#endif#ifndef B57600#define B57600  B38400#endif#ifndef B76800#define B76800  B57600#endif#ifndef B115200#define B115200 B76800#endif#ifndef B230400#define B230400 B115200#endifstruct termspeeds{  unsigned int speed;  unsigned int sym;} termspeeds[] ={  { 0,     B0 },     { 50,    B50 },   { 75,    B75 },  { 110,   B110 },   { 134,   B134 },  { 150,   B150 },  { 200,   B200 },   { 300,   B300 },  { 600,   B600 },  { 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },  { 4800,   B4800 },   { 7200,  B7200 },  { 9600,   B9600 },  { 14400,  B14400 },  { 19200, B19200 }, { 28800,  B28800 },  { 38400,  B38400 },  { 57600, B57600 }, { 115200, B115200 },  { 230400, B230400 }, { -1,    B230400 }};unsigned intspeed_translate (unsigned int sym){  unsigned int i;  for (i = 0; i < (sizeof (termspeeds) / sizeof (*termspeeds)); i++)    {      if (termspeeds[i].sym == sym)	return termspeeds[i].speed;    }  return 0;}/* Returns the terminal speed for the file descriptor FD, or   SPEED_NOTATTY if FD is not associated with a terminal.  */intspeed (int fd){  struct termios tt;  if (tcgetattr (fd, &tt) == 0)    {      /* speed_t sp; */      unsigned int sp = cfgetispeed (&tt);      return speed_translate (sp);    }  return SPEED_NOTATTY;}pid_t child;struct termios deftt;struct termios nott;voiddoit (sigset_t *smask){  int i;  for (i = 0; i < NCCS; i++)    nott.c_cc[i] = _POSIX_VDISABLE;  tcgetattr(0, &deftt);  nott.c_cc[VSTART] = deftt.c_cc[VSTART];  nott.c_cc[VSTOP] = deftt.c_cc[VSTOP];  setsig (SIGINT, SIG_IGN);  setsignal (SIGHUP);  setsignal (SIGQUIT);  child = fork ();  if (child == -1)    {      warn ("fork");      done (1);    }  if (child == 0)    {      mode (1);      if (reader (smask) == 0)	{	  /* If the reader () return 0, the socket to the server returned an	     EOF, meaning the client logged out of the remote system.	     This is the normal termination.  */	  msg ("connection closed.");	  exit (0);	}      /* If the reader () returns nonzero, the socket to the server	 returned an error.  Somethingg went wrong.  */      sleep (1);      msg ("\007connection closed."); /* 007 == ASCII bell.  */      exit (1);    }  /*   * Parent process == writer.   *   * We may still own the socket, and may have a pending SIGURG (or might   * receive one soon) that we really want to send to the reader.  When   * one of these comes in, the trap copytochild simply copies such

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -