📄 rlogin.c
字号:
/* * Copyright (c) 1983, 1990 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 lintchar copyright[] ="@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lint#ifdef IDstatic char sccsid[] = "@(#)rlogin.c 5.33 (Berkeley) 3/1/91";#endif#endif /* not lint *//* * $Source: mit/rlogin/RCS/rlogin.c,v $ * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall * Exp Locker: kfall $ *//* * rlogin - remote login */#include <sys/ioctl.h>#include <sys/types.h>#include <sys/wait.h>#include <net/netlib.h>#include <net/hton.h>#include <net/gen/in.h>#include <net/gen/netdb.h>#include <net/gen/tcp.h>#include <net/gen/tcp_io.h>#include <termios.h>#include <setjmp.h>#include <errno.h>#include <pwd.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <assert.h>#include <ctype.h>#include <fcntl.h>#include <signal.h>#include <stdlib.h>#if __minixtypedef unsigned char u_char;#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;extern char *krb_realmofhost();#endif#ifndef TIOCPKT_WINDOW#define TIOCPKT_WINDOW 0x80#endif/* concession to Sun */#ifndef SIGUSR1#define SIGUSR1 30#endif/* standard Minix doesn't really have SIGCHLD */#if __minix && !__minix_vmd#undef SIGCHLD#define SIGCHLD SIGTERM#endifextern int errno;int eight, litout, rem;int noescape;u_char escapechar = '~';struct speed{ speed_t speed; char *name;} speeds[] = { { B0, "0" }, { B50, "50" }, { B75, "75" }, { B110, "110" }, { B134, "134" }, { B150, "150" }, { B200, "200" }, { B300, "300" }, { B600, "600" }, { B1200, "1200" }, { B1800, "1800" }, { B2400, "2400" }, { B4800, "4800" }, { B9600, "9600" }, { B19200, "19200" }, { B38400, "38400" }, { B57600, "57600" }, { B115200, "115200" }, { -1, NULL },};#if __minix_vmd/* flow control variables */int more2read_0;int inprogress_0;int more2write_1;int inprogress_1;int more2read_rem;int inprogress_rd_rem;int more2write_rem;int inprogress_wr_rem;/* write to remote */size_t wr_rem_size;size_t wr_rem_offset;size_t extra_wr_rem_size;size_t extra_wr_rem_offset;char *extra_wr_rem;size_t extra_wr_rem_new_size;char *extra_wr_rem_new;#endif /* __minix_vmd */struct winsize winsize;#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)extern int main _ARGS(( int argc, char **argv ));static void usage _ARGS(( void ));static u_char getescape _ARGS(( char *p ));static char *speeds2str _ARGS(( speed_t speed ));static void lostpeer _ARGS(( int sig ));static void doit _ARGS(( void ));static void setsignal _ARGS(( int sig, void (*act)(int sig) ));static void msg _ARGS(( char *str ));static void done _ARGS(( int status ));#if !__minix_vmdstatic int reader _ARGS(( void ));#endifstatic void mode _ARGS(( int f ));#if __minix_vmdstatic void mark_async _ARGS(( int fd ));static void init_0 _ARGS(( void ));static void init_1 _ARGS(( void ));static void init_rd_rem _ARGS(( void ));static void init_wr_rem _ARGS(( void ));static void restart_0 _ARGS(( void ));static void restart_1 _ARGS(( void ));static void restart_rd_rem _ARGS(( void ));static void restart_wr_rem _ARGS(( void ));static void completed_0 _ARGS(( int result, int error ));static void completed_1 _ARGS(( int result, int error ));static void completed_rd_rem _ARGS(( int result, int error ));static void completed_wr_rem _ARGS(( int result, int error ));static void do_urg _ARGS(( int urg_byte ));#endif#if !__minix_vmdstatic void catch_child _ARGS(( int sig ));static void writer _ARGS(( void ));#endifstatic void echo _ARGS(( int c ));#if __minix_vmdstatic void finish _ARGS(( void ));static void sendwindow _ARGS(( void ));static void sigwinch _ARGS(( int sig ));static void subshell _ARGS(( void ));#endifint main(argc, argv) int argc; char **argv;{ extern char *optarg; extern int optind; struct passwd *pw; struct servent *sp; struct termios ttyb;#if __minix_vmd nwio_tcpopt_t tcpopt; int error;#endif 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': 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 (tcgetattr(0, &ttyb) == 0) { (void)strcat(term, "/"); (void)strcat(term, speeds2str(cfgetospeed(&ttyb))); } (void)get_window_size(0, &winsize); (void)signal(SIGPIPE, lostpeer);#ifdef KERBEROStry_connect: if (use_kerberos) { 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 __minix_vmd /* Enable BSD compatibility for urgent data. */ tcpopt.nwto_flags= NWTO_BSD_URG; error= ioctl(rem, NWIOSTCPOPT, &tcpopt); if (error == -1) { fprintf(stderr, "rlogin: NWIOSTCPOPT failed: %s\n", strerror(errno)); }#endif (void)setuid(uid); doit(); /*NOTREACHED*/}struct termios defattr, rawattr;#if __minix_vmdint mustsendwindow;#elseint child;#endifstatic voiddoit(){ struct termios sb;#if !__minix_vmd int r;#else asio_fd_set_t fd_set; struct fwait fw; int result;#endif (void)tcgetattr(0, &sb); defattr = sb; rawattr = sb; rawattr.c_iflag &= ~(ICRNL | IGNCR | INLCR | ISTRIP | IXOFF | IXON | PARMRK | IXANY); rawattr.c_oflag &= ~(OPOST); rawattr.c_lflag &= ~(ECHONL | ECHO | ICANON | IEXTEN | ISIG); (void)signal(SIGINT, SIG_IGN); setsignal(SIGHUP, exit); setsignal(SIGQUIT, exit);#if !__minix_vmd child = fork(); if (child == -1) { (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); done(1); } if (child == 0) { mode(1); r = reader(); if (r == 0) { msg("connection closed.");#if __minix && !__minix_vmd kill(getppid(), SIGCHLD);#endif exit(0); } sleep(1); msg("\007connection closed.");#if __minix && !__minix_vmd kill(getppid(), SIGCHLD);#endif exit(1); } (void)signal(SIGCHLD, catch_child); writer();#else /* __minix_vmd */ mode(1); /* mark the file descriptors 0, 1, and rem as asynchronous. */ mark_async(0); mark_async(1); mark_async(rem); init_0(); init_1(); init_rd_rem(); init_wr_rem(); for (;;) { ASIO_FD_ZERO(&fd_set); fw.fw_flags= 0; fw.fw_bits= fd_set.afds_bits; fw.fw_maxfd= ASIO_FD_SETSIZE; if (more2read_0 && !inprogress_0) { restart_0(); fw.fw_flags |= FWF_NONBLOCK; } if (more2write_1 && !inprogress_1) { restart_1(); fw.fw_flags |= FWF_NONBLOCK; } if (more2read_rem && !inprogress_rd_rem) { restart_rd_rem(); fw.fw_flags |= FWF_NONBLOCK; } if (more2write_rem && !inprogress_wr_rem) { restart_wr_rem(); fw.fw_flags |= FWF_NONBLOCK; } if (more2read_0 && inprogress_0) ASIO_FD_SET(0, ASIO_READ, &fd_set); if (more2write_1 && inprogress_1) ASIO_FD_SET(1, ASIO_WRITE, &fd_set); if (more2read_rem && inprogress_rd_rem) ASIO_FD_SET(rem, ASIO_READ, &fd_set); if (more2write_rem && inprogress_wr_rem) ASIO_FD_SET(rem, ASIO_WRITE, &fd_set); for (;;) { result= fwait(&fw); if (result == -1 && (errno == EAGAIN || errno == EINTR)) { break; } if (result == -1) { fprintf(stderr, "fwait failed (%s)\n", strerror(errno)); exit(1); } assert(result == 0);#if 0printf("fwait: fw_fw= %d, fw_operation= %d, fw_result= %d, fw.fw_errno= %d\n", fw.fw_fd, fw.fw_operation, fw.fw_result, fw.fw_errno);#endif if (fw.fw_fd == 0 && fw.fw_operation == ASIO_READ) { completed_0(fw.fw_result, fw.fw_errno); } else if (fw.fw_fd == 1 && fw.fw_operation == ASIO_WRITE) { completed_1(fw.fw_result, fw.fw_errno); } else if (fw.fw_fd == rem && fw.fw_operation == ASIO_READ) { completed_rd_rem(fw.fw_result, fw.fw_errno); } else if (fw.fw_fd == rem && fw.fw_operation == ASIO_WRITE) { completed_wr_rem(fw.fw_result, fw.fw_errno); } else { fprintf(stderr, "strange result from fwait: fd= %d, operation= %d\n", fw.fw_fd, fw.fw_operation); exit(1); } if (!(fw.fw_flags & FWF_MORE)) break; } if (mustsendwindow) { mustsendwindow= 0; sendwindow(); } }#endif /* __minix_vmd */ msg("connection closed."); done(0);}/* trap a signal, unless it is being ignored. */static voidsetsignal(sig, act) int sig; void (*act) _ARGS(( int sig ));{ if (signal(sig, act) == SIG_IGN) (void)signal(sig, SIG_IGN);}static voiddone(status) int status;{ int w, wstatus; mode(0);#if !__minix_vmd 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); }#endif exit(status);}int dosigwinch;#if !__minixvoid sigwinch();#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -