📄 rlogin.c
字号:
/* * Copyright (c) 1983, 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. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)rlogin.c 8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * rlogin - remote login */#include <sys/param.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/wait.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <pwd.h>#include <setjmp.h>#include <sgtty.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifdef __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#ifdef KERBEROS#include <kerberosIV/des.h>#include <kerberosIV/krb.h>#include "krb.h"CREDENTIALS cred;Key_schedule schedule;int use_kerberos = 1, doencrypt;char dst_realm_buf[REALM_SZ], *dest_realm = NULL;#endif#ifndef TIOCPKT_WINDOW#define TIOCPKT_WINDOW 0x80#endif/* concession to Sun */#ifndef SIGUSR1#define SIGUSR1 30#endifint eight, litout, rem;int noescape;u_char escapechar = '~';char *speeds[] = { "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400"};#ifdef OLDSUNstruct winsize { unsigned short ws_row, ws_col; unsigned short ws_xpixel, ws_ypixel;};#else#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)#endifstruct winsize winsize;void catch_child __P((int));void copytochild __P((int));__dead void doit __P((long));__dead void done __P((int));void echo __P((char));u_int getescape __P((char *));void lostpeer __P((int));void mode __P((int));void msg __P((char *));void oob __P((int));int reader __P((int));void sendwindow __P((void));void setsignal __P((int));void sigwinch __P((int));void stop __P((char));__dead void usage __P((void));void writer __P((void));void writeroob __P((int));#ifdef KERBEROSvoid warning __P((const char *, ...));#endif#ifdef OLDSUNint get_window_size __P((int, struct winsize *));#endifintmain(argc, argv) int argc; char *argv[];{ extern char *optarg; extern int optind; struct passwd *pw; struct servent *sp; struct sgttyb ttyb; long omask; int argoff, ch, dflag, one, uid; char *host, *p, *user, term[1024]; argoff = dflag = 0; one = 1; host = user = NULL; if (p = rindex(argv[0], '/')) ++p; else p = argv[0]; if (strcmp(p, "rlogin")) host = p; /* handle "rlogin host flags" */ if (!host && argc > 2 && argv[1][0] != '-') { host = argv[1]; argoff = 1; }#ifdef KERBEROS#define OPTIONS "8EKLde:k:l:x"#else#define OPTIONS "8EKLde:l:"#endif while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) switch(ch) { case '8': eight = 1; break; case 'E': noescape = 1; break; case 'K':#ifdef KERBEROS use_kerberos = 0;#endif break; case 'L': litout = 1; break; case 'd': dflag = 1; break; case 'e': noescape = 0; escapechar = getescape(optarg); break;#ifdef KERBEROS case 'k': dest_realm = dst_realm_buf; (void)strncpy(dest_realm, optarg, REALM_SZ); break;#endif case 'l': user = optarg; break;#ifdef CRYPT#ifdef KERBEROS case 'x': doencrypt = 1; des_set_key(cred.session, schedule); break;#endif#endif case '?': default: usage(); } optind += argoff; argc -= optind; argv += optind; /* if haven't gotten a host yet, do so */ if (!host && !(host = *argv++)) usage(); if (*argv) usage(); if (!(pw = getpwuid(uid = getuid()))) { (void)fprintf(stderr, "rlogin: unknown user id.\n"); exit(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 if (sp == NULL) sp = getservbyname("login", "tcp"); if (sp == NULL) { (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); exit(1); } (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); if (ioctl(0, TIOCGETP, &ttyb) == 0) { (void)strcat(term, "/"); (void)strcat(term, speeds[(int)ttyb.sg_ospeed]); } (void)get_window_size(0, &winsize); (void)signal(SIGPIPE, lostpeer); /* will use SIGUSR1 for window size hack, so hold it off */ omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); /* * 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. */ (void)signal(SIGURG, copytochild); (void)signal(SIGUSR1, writeroob);#ifdef KERBEROStry_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))) { (void)fprintf(stderr, "rlogin: %s\n", strerror(ENOMEM)); exit(1); } rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost(host);#ifdef CRYPT 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) { (void)fprintf(stderr, "rlogin: unknown service login/tcp.\n"); exit(1); } 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 CRYPT if (doencrypt) { (void)fprintf(stderr, "rlogin: the -x flag requires Kerberos authentication.\n"); exit(1); }#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); if (dflag && setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", strerror(errno)); one = IPTOS_LOWDELAY; if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0) perror("rlogin: setsockopt TOS (ignored)"); (void)setuid(uid); doit(omask); /*NOTREACHED*/}int child, defflags, deflflags, tabflag;char deferase, defkill;struct tchars deftc;struct ltchars defltc;struct tchars notc = { -1, -1, -1, -1, -1, -1 };struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };voiddoit(omask) long omask;{ struct sgttyb sb; (void)ioctl(0, TIOCGETP, (char *)&sb); defflags = sb.sg_flags; tabflag = defflags & TBDELAY; defflags &= ECHO | CRMOD; deferase = sb.sg_erase; defkill = sb.sg_kill; (void)ioctl(0, TIOCLGET, &deflflags); (void)ioctl(0, TIOCGETC, &deftc); notc.t_startc = deftc.t_startc; notc.t_stopc = deftc.t_stopc; (void)ioctl(0, TIOCGLTC, &defltc); (void)signal(SIGINT, SIG_IGN); setsignal(SIGHUP); setsignal(SIGQUIT); child = fork(); if (child == -1) { (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); done(1); } if (child == 0) { mode(1); if (reader(omask) == 0) { msg("connection closed."); exit(0); } sleep(1); msg("\007connection closed."); exit(1); } /* * 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 * signals to the child. We can now unblock SIGURG and SIGUSR1 * that were set above. */ (void)sigsetmask(omask); (void)signal(SIGCHLD, catch_child); writer(); msg("closed connection."); done(0);}/* trap a signal, unless it is being ignored. */voidsetsignal(sig) int sig;{ int omask = sigblock(sigmask(sig)); if (signal(sig, exit) == SIG_IGN) (void)signal(sig, SIG_IGN); (void)sigsetmask(omask);}__dead voiddone(status) int status;{ int w, wstatus; mode(0); if (child > 0) { /* make sure catch_child does not snap it up */ (void)signal(SIGCHLD, SIG_DFL); if (kill(child, SIGKILL) >= 0) while ((w = wait(&wstatus)) > 0 && w != child); } exit(status);}int dosigwinch;/* * This is called when the reader process gets the out-of-band (urgent) * request to turn on the window-changing protocol. */voidwriteroob(signo) int signo;{ if (dosigwinch == 0) { sendwindow(); (void)signal(SIGWINCH, sigwinch); } dosigwinch = 1;}voidcatch_child(signo) int signo;{ union wait status; int pid; for (;;) { pid = wait3((int *)&status, WNOHANG|WUNTRACED, NULL); if (pid == 0) return; /* if the child (reader) dies, just quit */ if (pid < 0 || (pid == child && !WIFSTOPPED(status))) done((int)(status.w_termsig | status.w_retcode)); } /* NOTREACHED */}/* * writer: write to remote: 0 -> line. * ~. terminate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -