X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ba29c5a2b6515d952ba2bd6c341e99458761c7cf..9bccbd7c566bbf4900f2bd91d2b2c3d4506740a2:/usr/src/usr.bin/rlogin/rlogin.c diff --git a/usr/src/usr.bin/rlogin/rlogin.c b/usr/src/usr.bin/rlogin/rlogin.c index b8fc63cab9..db583603d8 100644 --- a/usr/src/usr.bin/rlogin/rlogin.c +++ b/usr/src/usr.bin/rlogin/rlogin.c @@ -1,358 +1,429 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1983, 1990 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% */ #ifndef lint char copyright[] = -"@(#) Copyright (c) 1983 Regents of the University of California.\n\ +"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\ All rights reserved.\n"; -#endif not lint +#endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)rlogin.c 5.12 (Berkeley) %G%"; -#endif not lint +static char sccsid[] = "@(#)rlogin.c 5.37 (Berkeley) %G%"; +#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 -#include #include #include +#include #include #include #include #include +#include +#include +#include -#include #include +#include +#include #include #include -#include -#include -#include +#include +#include +#include + +#ifdef KERBEROS +#include +#include + +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 TIOCPKT_WINDOW - -/* concession to sun */ -# ifndef SIGUSR1 -# define SIGUSR1 30 -# endif SIGUSR1 - -char *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy(); -struct passwd *getpwuid(); -char *name; -int rem; -char cmdchar = '~'; -int eight; -int litout; -char *speeds[] = - { "0", "50", "75", "110", "134", "150", "200", "300", - "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; -char term[256] = "network"; -extern int errno; -int lostpeer(); -int dosigwinch = 0; -#ifndef sigmask -#define sigmask(m) (1 << ((m)-1)) +#ifndef TIOCPKT_WINDOW +#define TIOCPKT_WINDOW 0x80 #endif + +/* concession to Sun */ +#ifndef SIGUSR1 +#define SIGUSR1 30 +#endif + +int 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 sun struct winsize { unsigned short ws_row, ws_col; unsigned short ws_xpixel, ws_ypixel; }; -#endif sun +#endif struct winsize winsize; -int sigwinch(), oob(); -/* - * The following routine provides compatibility (such as it is) - * between 4.2BSD Suns and others. Suns have only a `ttysize', - * so we convert it to a winsize. - */ -#ifdef sun -int -get_window_size(fd, wp) - int fd; - struct winsize *wp; -{ - struct ttysize ts; - int error; +#ifndef sun +#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) +#endif - if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) - return (error); - wp->ws_row = ts.ts_lines; - wp->ws_col = ts.ts_cols; - wp->ws_xpixel = 0; - wp->ws_ypixel = 0; - return (0); -} -#else sun -#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) -#endif sun +void exit(); main(argc, argv) int argc; char **argv; { - char *host, *cp; - struct sgttyb ttyb; - struct passwd *pwd; + extern char *optarg; + extern int optind; + struct passwd *pw; struct servent *sp; - int uid, options = 0, oldmask; - int on = 1; - - host = rindex(argv[0], '/'); - if (host) - host++; + struct hostent *hp; + struct sgttyb ttyb; + long omask; + int argoff, ch, dflag, one, uid; + char *host, *p, *user, term[1024]; + void lostpeer(), copytochild(), writeroob(); + u_char getescape(); + char *getenv(); + + argoff = dflag = 0; + one = 1; + host = user = NULL; + + if (p = rindex(argv[0], '/')) + ++p; else - host = argv[0]; - argv++, --argc; - if (!strcmp(host, "rlogin")) - host = *argv++, --argc; -another: - if (argc > 0 && !strcmp(*argv, "-d")) { - argv++, argc--; - options |= SO_DEBUG; - goto another; - } - if (argc > 0 && !strcmp(*argv, "-l")) { - argv++, argc--; - if (argc == 0) - goto usage; - name = *argv++; argc--; - goto another; - } - if (argc > 0 && !strncmp(*argv, "-e", 2)) { - cmdchar = argv[0][2]; - argv++, argc--; - goto another; + 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; } - if (argc > 0 && !strcmp(*argv, "-8")) { - eight = 1; - argv++, argc--; - goto another; + +#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; + 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 (argc > 0 && !strcmp(*argv, "-L")) { - litout = 1; - argv++, argc--; - goto another; + 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"); + } } - if (host == 0) - goto usage; - if (argc > 0) - goto usage; - pwd = getpwuid(getuid()); - if (pwd == 0) { - fprintf(stderr, "Who are you?\n"); +#endif + if (sp == NULL) + sp = getservbyname("login", "tcp"); + if (sp == NULL) { + (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); exit(1); } - sp = getservbyname("login", "tcp"); - if (sp == 0) { - fprintf(stderr, "rlogin: login/tcp: unknown service\n"); - exit(2); - } - cp = getenv("TERM"); - if (cp) - (void) strcpy(term, cp); + + (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); if (ioctl(0, TIOCGETP, &ttyb) == 0) { - (void) strcat(term, "/"); - (void) strcat(term, speeds[ttyb.sg_ospeed]); + (void)strcat(term, "/"); + (void)strcat(term, speeds[ttyb.sg_ospeed]); } - (void) get_window_size(0, &winsize); - (void) signal(SIGPIPE, lostpeer); + + (void)get_window_size(0, &winsize); + + (void)signal(SIGPIPE, lostpeer); /* will use SIGUSR1 for window size hack, so hold it off */ - oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); - rem = rcmd(&host, sp->s_port, pwd->pw_name, - name ? name : pwd->pw_name, term, 0); - if (rem < 0) - exit(1); - if (options & SO_DEBUG && - setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) - perror("rlogin: setsockopt (SO_DEBUG)"); - uid = getuid(); - if (setuid(uid) < 0) { - perror("rlogin: setuid"); - exit(1); + 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 KERBEROS +try_connect: + if (use_kerberos) { + /* 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); + + 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 { + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); } - doit(oldmask); - /*NOTREACHED*/ -usage: - fprintf(stderr, - "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n"); - exit(1); -} +#else + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); +#endif /* KERBEROS */ -#define CRLF "\r\n" + if (rem < 0) + exit(1); -int child; -int catchild(); -int copytochild(), writeroob(); + 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 defflags, tabflag; -int deflflags; -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 }; +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 }; -doit(oldmask) +doit(omask) + long omask; { - int exit(); struct sgttyb sb; + void catch_child(), exit(); - (void) ioctl(0, TIOCGETP, (char *)&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, (char *)&deflflags); - (void) ioctl(0, TIOCGETC, (char *)&deftc); + (void)ioctl(0, TIOCLGET, (char *)&deflflags); + (void)ioctl(0, TIOCGETC, (char *)&deftc); notc.t_startc = deftc.t_startc; notc.t_stopc = deftc.t_stopc; - (void) ioctl(0, TIOCGLTC, (char *)&defltc); - (void) signal(SIGINT, SIG_IGN); + (void)ioctl(0, TIOCGLTC, (char *)&defltc); + (void)signal(SIGINT, SIG_IGN); setsignal(SIGHUP, exit); setsignal(SIGQUIT, exit); child = fork(); if (child == -1) { - perror("rlogin: fork"); + (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); done(1); } if (child == 0) { mode(1); - if (reader(oldmask) == 0) { - prf("Connection closed."); + if (reader(omask) == 0) { + msg("connection closed."); exit(0); } sleep(1); - prf("\007Connection closed."); - exit(3); + 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. Set a trap that simply copies such signals to - * the child. + * 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) signal(SIGURG, copytochild); - (void) signal(SIGUSR1, writeroob); - (void) sigsetmask(oldmask); - (void) signal(SIGCHLD, catchild); + (void)sigsetmask(omask); + (void)signal(SIGCHLD, catch_child); writer(); - prf("Closed connection."); + msg("closed connection."); done(0); } -/* - * Trap a signal, unless it is being ignored. - */ +/* trap a signal, unless it is being ignored. */ setsignal(sig, act) - int sig, (*act)(); + int sig; + void (*act)(); { int omask = sigblock(sigmask(sig)); if (signal(sig, act) == SIG_IGN) - (void) signal(sig, SIG_IGN); - (void) sigsetmask(omask); + (void)signal(sig, SIG_IGN); + (void)sigsetmask(omask); } done(status) int status; { - int w; + int w, wstatus; mode(0); if (child > 0) { - /* make sure catchild does not snap it up */ - (void) signal(SIGCHLD, SIG_DFL); + /* make sure catch_child does not snap it up */ + (void)signal(SIGCHLD, SIG_DFL); if (kill(child, SIGKILL) >= 0) - while ((w = wait((union wait *)0)) > 0 && w != child) - /*void*/; + while ((w = wait(&wstatus)) > 0 && w != child); } exit(status); } -/* - * Copy SIGURGs to the child process. - */ -copytochild() -{ - - (void) kill(child, SIGURG); -} +int dosigwinch; +void sigwinch(); /* * This is called when the reader process gets the out-of-band (urgent) * request to turn on the window-changing protocol. */ +void writeroob() { - if (dosigwinch == 0) { sendwindow(); - (void) signal(SIGWINCH, sigwinch); + (void)signal(SIGWINCH, sigwinch); } dosigwinch = 1; } -catchild() +void +catch_child() { union wait status; int pid; -again: - pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); - 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)); - goto again; + 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 - * ~^Z suspend rlogin process. - * ~^Y suspend rlogin process, but leave reader alone. + * ~. terminate + * ~^Z suspend rlogin process. + * ~ suspend rlogin process, but leave reader alone. */ writer() { + register int bol, local, n; char c; - register n; - register bol = 1; /* beginning of line */ - register local = 0; + bol = 1; /* beginning of line */ + local = 0; for (;;) { - n = read(0, &c, 1); + n = read(STDIN_FILENO, &c, 1); if (n <= 0) { if (n < 0 && errno == EINTR) continue; break; } /* - * If we're at the beginning of the line - * and recognize a command character, then - * we echo locally. Otherwise, characters - * are echo'd remotely. If the command - * character is doubled, this acts as a - * force and local echo is suppressed. + * If we're at the beginning of the line and recognize a + * command character, then we echo locally. Otherwise, + * characters are echo'd remotely. If the command character + * is doubled, this acts as a force and local echo is + * suppressed. */ if (bol) { bol = 0; - if (c == cmdchar) { - bol = 0; + if (!noescape && c == escapechar) { local = 1; continue; } @@ -368,13 +439,14 @@ writer() stop(c); continue; } - if (c != cmdchar) - (void) write(rem, &cmdchar, 1); - } - if (write(rem, &c, 1) == 0) { - prf("line gone"); - break; + if (c != escapechar) + (void)write(rem, &escapechar, 1); } + + if (write(rem, &c, 1) == 0) { + msg("line gone"); + break; + } bol = c == defkill || c == deftc.t_eofc || c == deftc.t_intrc || c == defltc.t_suspc || c == '\r' || c == '\n'; @@ -384,11 +456,12 @@ writer() echo(c) register char c; { + register char *p; char buf[8]; - register char *p = buf; + p = buf; c &= 0177; - *p++ = cmdchar; + *p++ = escapechar; if (c < ' ') { *p++ = '^'; *p++ = c + '@'; @@ -399,26 +472,27 @@ register char c; *p++ = c; *p++ = '\r'; *p++ = '\n'; - (void) write(1, buf, p - buf); + (void)write(STDOUT_FILENO, buf, p - buf); } stop(cmdc) char cmdc; { mode(0); - (void) signal(SIGCHLD, SIG_IGN); - (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); - (void) signal(SIGCHLD, catchild); + (void)signal(SIGCHLD, SIG_IGN); + (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); + (void)signal(SIGCHLD, catch_child); mode(1); sigwinch(); /* check for size changes */ } +void sigwinch() { struct winsize ws; if (dosigwinch && get_window_size(0, &ws) == 0 && - bcmp(&ws, &winsize, sizeof (ws))) { + bcmp(&ws, &winsize, sizeof(ws))) { winsize = ws; sendwindow(); } @@ -429,9 +503,10 @@ sigwinch() */ sendwindow() { + struct winsize *wp; char obuf[4 + sizeof (struct winsize)]; - struct winsize *wp = (struct winsize *)(obuf+4); + wp = (struct winsize *)(obuf+4); obuf[0] = 0377; obuf[1] = 0377; obuf[2] = 's'; @@ -440,7 +515,8 @@ sendwindow() wp->ws_col = htons(winsize.ws_col); wp->ws_xpixel = htons(winsize.ws_xpixel); wp->ws_ypixel = htons(winsize.ws_ypixel); - (void) write(rem, obuf, sizeof(obuf)); + + (void)write(rem, obuf, sizeof(obuf)); } /* @@ -449,32 +525,30 @@ sendwindow() #define READING 1 #define WRITING 2 -char rcvbuf[8 * 1024]; -int rcvcnt; -int rcvstate; -int ppid; -jmp_buf rcvtop; +jmp_buf rcvtop; +int ppid, rcvcnt, rcvstate; +char rcvbuf[8 * 1024]; +void oob() { - int out = FWRITE, atmark, n; - int rcvd = 0; - char waste[BUFSIZ], mark; struct sgttyb sb; + int atmark, n, out, rcvd; + char waste[BUFSIZ], mark; + out = O_RDWR; + rcvd = 0; while (recv(rem, &mark, 1, MSG_OOB) < 0) switch (errno) { - case EWOULDBLOCK: /* - * Urgent data not here yet. - * It may not be possible to send it yet - * if we are blocked for output - * and our input buffer is full. + * Urgent data not here yet. It may not be possible + * to send it yet if we are blocked for output and + * our input buffer is full. */ if (rcvcnt < sizeof(rcvbuf)) { n = read(rem, rcvbuf + rcvcnt, - sizeof(rcvbuf) - rcvcnt); + sizeof(rcvbuf) - rcvcnt); if (n <= 0) return; rcvd += n; @@ -484,39 +558,37 @@ oob() return; } continue; - default: return; } if (mark & TIOCPKT_WINDOW) { - /* - * Let server know about window size changes - */ - (void) kill(ppid, SIGUSR1); + /* Let server know about window size changes */ + (void)kill(ppid, SIGUSR1); } if (!eight && (mark & TIOCPKT_NOSTOP)) { - (void) ioctl(0, TIOCGETP, (char *)&sb); + (void)ioctl(0, TIOCGETP, (char *)&sb); sb.sg_flags &= ~CBREAK; sb.sg_flags |= RAW; - (void) ioctl(0, TIOCSETN, (char *)&sb); + (void)ioctl(0, TIOCSETN, (char *)&sb); notc.t_stopc = -1; notc.t_startc = -1; - (void) ioctl(0, TIOCSETC, (char *)¬c); + (void)ioctl(0, TIOCSETC, (char *)¬c); } if (!eight && (mark & TIOCPKT_DOSTOP)) { - (void) ioctl(0, TIOCGETP, (char *)&sb); + (void)ioctl(0, TIOCGETP, (char *)&sb); sb.sg_flags &= ~RAW; sb.sg_flags |= CBREAK; - (void) ioctl(0, TIOCSETN, (char *)&sb); + (void)ioctl(0, TIOCSETN, (char *)&sb); notc.t_stopc = deftc.t_stopc; notc.t_startc = deftc.t_startc; - (void) ioctl(0, TIOCSETC, (char *)¬c); + (void)ioctl(0, TIOCSETC, (char *)¬c); } if (mark & TIOCPKT_FLUSHWRITE) { - (void) ioctl(1, TIOCFLUSH, (char *)&out); + (void)ioctl(1, TIOCFLUSH, (char *)&out); for (;;) { if (ioctl(rem, SIOCATMARK, &atmark) < 0) { - perror("ioctl"); + (void)fprintf(stderr, "rlogin: ioctl: %s.\n", + strerror(errno)); break; } if (atmark) @@ -526,35 +598,32 @@ oob() break; } /* - * Don't want any pending data to be output, - * so clear the recv buffer. - * If we were hanging on a write when interrupted, - * don't want it to restart. If we were reading, - * restart anyway. + * Don't want any pending data to be output, so clear the recv + * buffer. If we were hanging on a write when interrupted, + * don't want it to restart. If we were reading, restart + * anyway. */ rcvcnt = 0; longjmp(rcvtop, 1); } - /* - * oob does not do FLUSHREAD (alas!) - */ + /* oob does not do FLUSHREAD (alas!) */ /* - * If we filled the receive buffer while a read was pending, - * longjmp to the top to restart appropriately. Don't abort - * a pending write, however, or we won't know how much was written. + * If we filled the receive buffer while a read was pending, longjmp + * to the top to restart appropriately. Don't abort a pending write, + * however, or we won't know how much was written. */ if (rcvd && rcvstate == READING) longjmp(rcvtop, 1); } -/* - * reader: read from remote: line -> 1 - */ -reader(oldmask) - int oldmask; +/* reader: read from remote: line -> 1 */ +reader(omask) + int omask; { + void oob(); + #if !defined(BSD) || BSD < 43 int pid = -getpid(); #else @@ -563,19 +632,19 @@ reader(oldmask) int n, remaining; char *bufp = rcvbuf; - (void) signal(SIGTTOU, SIG_IGN); - (void) signal(SIGURG, oob); + (void)signal(SIGTTOU, SIG_IGN); + (void)signal(SIGURG, oob); ppid = getppid(); - (void) fcntl(rem, F_SETOWN, pid); - (void) setjmp(rcvtop); - (void) sigsetmask(oldmask); + (void)fcntl(rem, F_SETOWN, pid); + (void)setjmp(rcvtop); + (void)sigsetmask(omask); for (;;) { while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { rcvstate = WRITING; - n = write(1, bufp, remaining); + n = write(STDOUT_FILENO, bufp, remaining); if (n < 0) { if (errno != EINTR) - return (-1); + return(-1); continue; } bufp += n; @@ -583,29 +652,30 @@ reader(oldmask) bufp = rcvbuf; rcvcnt = 0; rcvstate = READING; - rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); + + rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); if (rcvcnt == 0) return (0); if (rcvcnt < 0) { if (errno == EINTR) continue; - perror("read"); - return (-1); + (void)fprintf(stderr, "rlogin: read: %s.\n", + strerror(errno)); + return(-1); } } } mode(f) { - struct tchars *tc; struct ltchars *ltc; struct sgttyb sb; - int lflags; - - (void) ioctl(0, TIOCGETP, (char *)&sb); - (void) ioctl(0, TIOCLGET, (char *)&lflags); - switch (f) { + struct tchars *tc; + int lflags; + (void)ioctl(0, TIOCGETP, (char *)&sb); + (void)ioctl(0, TIOCLGET, (char *)&lflags); + switch(f) { case 0: sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); sb.sg_flags |= defflags|tabflag; @@ -615,7 +685,6 @@ mode(f) sb.sg_erase = deferase; lflags = deflflags; break; - case 1: sb.sg_flags |= (eight ? RAW : CBREAK); sb.sg_flags &= ~defflags; @@ -628,30 +697,107 @@ mode(f) if (litout) lflags |= LLITOUT; break; - default: return; } - (void) ioctl(0, TIOCSLTC, (char *)ltc); - (void) ioctl(0, TIOCSETC, (char *)tc); - (void) ioctl(0, TIOCSETN, (char *)&sb); - (void) ioctl(0, TIOCLSET, (char *)&lflags); + (void)ioctl(0, TIOCSLTC, (char *)ltc); + (void)ioctl(0, TIOCSETC, (char *)tc); + (void)ioctl(0, TIOCSETN, (char *)&sb); + (void)ioctl(0, TIOCLSET, (char *)&lflags); } -/*VARARGS*/ -prf(f, a1, a2, a3, a4, a5) - char *f; +void +lostpeer() { + (void)signal(SIGPIPE, SIG_IGN); + msg("\007connection closed."); + done(1); +} - fprintf(stderr, f, a1, a2, a3, a4, a5); - fprintf(stderr, CRLF); +/* copy SIGURGs to the child process. */ +void +copytochild() +{ + (void)kill(child, SIGURG); } -lostpeer() +msg(str) + char *str; { + (void)fprintf(stderr, "rlogin: %s\r\n", str); +} - (void) signal(SIGPIPE, SIG_IGN); - prf("\007Connection closed."); - done(1); +#ifdef KERBEROS +/* VARARGS */ +warning(va_alist) +va_dcl +{ + va_list ap; + char *fmt; + + (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); + va_start(ap); + fmt = va_arg(ap, char *); + vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, ".\n"); +} +#endif + +usage() +{ + (void)fprintf(stderr, + "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", +#ifdef KERBEROS + "8EKL", " [-k realm] "); +#else + "8EL", " "); +#endif + exit(1); +} + +/* + * The following routine provides compatibility (such as it is) between 4.2BSD + * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. + */ +#ifdef sun +get_window_size(fd, wp) + int fd; + struct winsize *wp; +{ + struct ttysize ts; + int error; + + if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) + return(error); + wp->ws_row = ts.ts_lines; + wp->ws_col = ts.ts_cols; + wp->ws_xpixel = 0; + wp->ws_ypixel = 0; + return(0); } +#endif +u_char +getescape(p) + register char *p; +{ + long val; + int len; + + if ((len = strlen(p)) == 1) /* use any single char, including '\' */ + return((u_char)*p); + /* otherwise, \nnn */ + if (*p == '\\' && len >= 2 && len <= 4) { + val = strtol(++p, (char **)NULL, 8); + for (;;) { + if (!*++p) + return((u_char)val); + if (*p < '0' || *p > '8') + break; + } + } + msg("illegal option value -- e"); + usage(); + /* NOTREACHED */ +}