several fixes for rlogin
Chris Torek
chris at mimsy.UUCP
Wed Mar 16 02:49:28 AEST 1988
Index: ucb/rlogin.c 4.3BSD Fix
Description:
Rlogin's window size information propagation is unreliable.
(I thought I had got this fixed before the 4.3 release, but
my RCS file says otherwise.)
rlogin is full of lint.
If the peer drops the connexion immediately after accepting it,
rlogin botches the tty settings.
Repeat-by:
The first and last are difficult. The middle is easy.
Fix:
Below. As a free bonus, this allows disabling the command
character entirely (via -enone). Some lint remains (I ran
out of energy).
RCS file: RCS/rlogin.c,v
retrieving revision 1.1
diff -c2 -r1.1 rlogin.c
*** /tmp/,RCSt1003990 Tue Mar 15 11:27:57 1988
--- rlogin.c Tue Mar 15 11:22:18 1988
***************
*** 12,16 ****
#ifndef lint
! static char sccsid[] = "@(#)rlogin.c 5.10 (Berkeley) 3/30/86";
#endif not lint
--- 12,16 ----
#ifndef lint
! static char sccsid[] = "@(#)rlogin.c 5.11 (Berkeley) 8/7/86";
#endif not lint
***************
*** 22,25 ****
--- 22,27 ----
#include <sys/file.h>
#include <sys/socket.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
#include <sys/wait.h>
***************
*** 38,46 ****
# endif TIOCPKT_WINDOW
! char *index(), *rindex(), *malloc(), *getenv();
struct passwd *getpwuid();
char *name;
int rem;
! char cmdchar = '~';
int eight;
int litout;
--- 40,53 ----
# 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;
! int cmdchar = '~';
int eight;
int litout;
***************
*** 56,60 ****
#endif
#ifdef sun
- struct ttysize winsize;
struct winsize {
unsigned short ws_row, ws_col;
--- 63,66 ----
***************
*** 61,69 ****
unsigned short ws_xpixel, ws_ypixel;
};
- #else sun
- struct winsize winsize;
#endif sun
int sigwinch(), oob();
main(argc, argv)
int argc;
--- 67,111 ----
unsigned short ws_xpixel, ws_ypixel;
};
#endif sun
+ struct winsize winsize;
int sigwinch(), oob();
+ /*
+ * tty mode information.
+ */
+ 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 };
+
+ /*
+ * 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;
+
+ 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
+
main(argc, argv)
int argc;
***************
*** 99,103 ****
}
if (argc > 0 && !strncmp(*argv, "-e", 2)) {
! cmdchar = argv[0][2];
argv++, argc--;
goto another;
--- 141,145 ----
}
if (argc > 0 && !strncmp(*argv, "-e", 2)) {
! cmdchar = strcmp(*argv, "-enone") ? argv[0][2] : -1;
argv++, argc--;
goto another;
***************
*** 129,145 ****
cp = getenv("TERM");
if (cp)
! strcpy(term, cp);
if (ioctl(0, TIOCGETP, &ttyb) == 0) {
! strcat(term, "/");
! strcat(term, speeds[ttyb.sg_ospeed]);
}
! #ifdef sun
! (void) ioctl(0, TIOCGSIZE, &winsize);
! #else sun
! (void) ioctl(0, TIOCGWINSZ, &winsize);
! #endif sun
! signal(SIGPIPE, lostpeer);
! signal(SIGURG, oob);
! oldmask = sigblock(sigmask(SIGURG));
rem = rcmd(&host, sp->s_port, pwd->pw_name,
name ? name : pwd->pw_name, term, 0);
--- 171,196 ----
cp = getenv("TERM");
if (cp)
! (void) strcpy(term, cp);
if (ioctl(0, TIOCGETP, &ttyb) == 0) {
! (void) strcat(term, "/");
! (void) strcat(term, speeds[ttyb.sg_ospeed]);
}
!
! /* set up the state, in case we lose peer early */
! defflags = ttyb.sg_flags;
! tabflag = defflags & TBDELAY;
! defflags &= ECHO | CRMOD;
! deferase = ttyb.sg_erase;
! defkill = ttyb.sg_kill;
! (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) 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);
***************
*** 166,198 ****
int child;
int catchild();
! int writeroob();
- 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 };
-
doit(oldmask)
{
int exit();
- struct sgttyb sb;
! ioctl(0, TIOCGETP, (char *)&sb);
! defflags = sb.sg_flags;
! tabflag = defflags & TBDELAY;
! defflags &= ECHO | CRMOD;
! deferase = sb.sg_erase;
! defkill = sb.sg_kill;
! ioctl(0, TIOCLGET, (char *)&deflflags);
! ioctl(0, TIOCGETC, (char *)&deftc);
! notc.t_startc = deftc.t_startc;
! notc.t_stopc = deftc.t_stopc;
! ioctl(0, TIOCGLTC, (char *)&defltc);
! signal(SIGINT, SIG_IGN);
! signal(SIGHUP, exit);
! signal(SIGQUIT, exit);
child = fork();
if (child == -1) {
--- 217,229 ----
int child;
int catchild();
! int copytochild(), writeroob();
doit(oldmask)
{
int exit();
! (void) signal(SIGINT, SIG_IGN);
! setsignal(SIGHUP, exit);
! setsignal(SIGQUIT, exit);
child = fork();
if (child == -1) {
***************
*** 202,207 ****
if (child == 0) {
mode(1);
! sigsetmask(oldmask);
! if (reader() == 0) {
prf("Connection closed.");
exit(0);
--- 233,237 ----
if (child == 0) {
mode(1);
! if (reader(oldmask) == 0) {
prf("Connection closed.");
exit(0);
***************
*** 211,217 ****
exit(3);
}
! signal(SIGURG, writeroob);
! sigsetmask(oldmask);
! signal(SIGCHLD, catchild);
writer();
prf("Closed connection.");
--- 241,255 ----
exit(3);
}
!
! /*
! * 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.
! */
! (void) signal(SIGURG, copytochild);
! (void) signal(SIGUSR1, writeroob);
! (void) sigsetmask(oldmask);
! (void) signal(SIGCHLD, catchild);
writer();
prf("Closed connection.");
***************
*** 219,229 ****
}
done(status)
int status;
{
mode(0);
! if (child > 0 && kill(child, SIGKILL) >= 0)
! wait((int *)0);
exit(status);
}
--- 257,286 ----
}
+ /*
+ * Trap a signal, unless it is being ignored.
+ */
+ setsignal(sig, act)
+ int sig, (*act)();
+ {
+ int omask = sigblock(sigmask(sig));
+
+ if (signal(sig, act) == SIG_IGN)
+ (void) signal(sig, SIG_IGN);
+ (void) sigsetmask(omask);
+ }
+
done(status)
int status;
{
+ int w;
mode(0);
! if (child > 0) {
! /* make sure catchild 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*/;
! }
exit(status);
}
***************
*** 230,233 ****
--- 287,299 ----
/*
+ * Copy SIGURGs to the child process.
+ */
+ copytochild()
+ {
+
+ (void) kill(child, SIGURG);
+ }
+
+ /*
* This is called when the reader process gets the out-of-band (urgent)
* request to turn on the window-changing protocol.
***************
*** 238,242 ****
if (dosigwinch == 0) {
sendwindow();
! signal(SIGWINCH, sigwinch);
}
dosigwinch = 1;
--- 304,308 ----
if (dosigwinch == 0) {
sendwindow();
! (void) signal(SIGWINCH, sigwinch);
}
dosigwinch = 1;
***************
*** 249,253 ****
again:
! pid = wait3(&status, WNOHANG|WUNTRACED, 0);
if (pid == 0)
return;
--- 315,319 ----
again:
! pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
if (pid == 0)
return;
***************
*** 256,260 ****
*/
if (pid < 0 || pid == child && !WIFSTOPPED(status))
! done(status.w_termsig | status.w_retcode);
goto again;
}
--- 322,326 ----
*/
if (pid < 0 || pid == child && !WIFSTOPPED(status))
! done((int)(status.w_termsig | status.w_retcode));
goto again;
}
***************
*** 307,312 ****
continue;
}
! if (c != cmdchar)
! write(rem, &cmdchar, 1);
}
if (write(rem, &c, 1) == 0) {
--- 373,380 ----
continue;
}
! if (c != cmdchar) {
! char cch = cmdchar;
! (void) write(rem, &cch, 1);
! }
}
if (write(rem, &c, 1) == 0) {
***************
*** 338,342 ****
*p++ = '\r';
*p++ = '\n';
! write(1, buf, p - buf);
}
--- 406,410 ----
*p++ = '\r';
*p++ = '\n';
! (void) write(1, buf, p - buf);
}
***************
*** 345,351 ****
{
mode(0);
! signal(SIGCHLD, SIG_IGN);
! kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
! signal(SIGCHLD, catchild);
mode(1);
sigwinch(); /* check for size changes */
--- 413,419 ----
{
mode(0);
! (void) signal(SIGCHLD, SIG_IGN);
! (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
! (void) signal(SIGCHLD, catchild);
mode(1);
sigwinch(); /* check for size changes */
***************
*** 352,373 ****
}
- #ifdef sun
sigwinch()
{
- struct ttysize ws;
-
- if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
- bcmp(&ws, &winsize, sizeof (ws))) {
- winsize = ws;
- sendwindow();
- }
- }
-
- #else sun
- sigwinch()
- {
struct winsize ws;
! if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
bcmp(&ws, &winsize, sizeof (ws))) {
winsize = ws;
--- 420,428 ----
}
sigwinch()
{
struct winsize ws;
! if (dosigwinch && get_window_size(0, &ws) == 0 &&
bcmp(&ws, &winsize, sizeof (ws))) {
winsize = ws;
***************
*** 375,379 ****
}
}
- #endif
/*
--- 430,433 ----
***************
*** 389,398 ****
obuf[2] = 's';
obuf[3] = 's';
- #ifdef sun
- wp->ws_row = htons(winsize.ts_lines);
- wp->ws_col = htons(winsize.ts_cols);
- wp->ws_xpixel = 0;
- wp->ws_ypixel = 0;
- #else sun
wp->ws_row = htons(winsize.ws_row);
wp->ws_col = htons(winsize.ws_col);
--- 443,446 ----
***************
*** 399,403 ****
wp->ws_xpixel = htons(winsize.ws_xpixel);
wp->ws_ypixel = htons(winsize.ws_ypixel);
- #endif sun
(void) write(rem, obuf, sizeof(obuf));
}
--- 447,450 ----
***************
*** 452,477 ****
* Let server know about window size changes
*/
! kill(ppid, SIGURG);
}
if (!eight && (mark & TIOCPKT_NOSTOP)) {
! ioctl(0, TIOCGETP, (char *)&sb);
sb.sg_flags &= ~CBREAK;
sb.sg_flags |= RAW;
! ioctl(0, TIOCSETN, (char *)&sb);
notc.t_stopc = -1;
notc.t_startc = -1;
! ioctl(0, TIOCSETC, (char *)¬c);
}
if (!eight && (mark & TIOCPKT_DOSTOP)) {
! ioctl(0, TIOCGETP, (char *)&sb);
sb.sg_flags &= ~RAW;
sb.sg_flags |= CBREAK;
! ioctl(0, TIOCSETN, (char *)&sb);
notc.t_stopc = deftc.t_stopc;
notc.t_startc = deftc.t_startc;
! ioctl(0, TIOCSETC, (char *)¬c);
}
if (mark & TIOCPKT_FLUSHWRITE) {
! ioctl(1, TIOCFLUSH, (char *)&out);
for (;;) {
if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
--- 499,524 ----
* Let server know about window size changes
*/
! (void) kill(ppid, SIGUSR1);
}
if (!eight && (mark & TIOCPKT_NOSTOP)) {
! (void) ioctl(0, TIOCGETP, (char *)&sb);
sb.sg_flags &= ~CBREAK;
sb.sg_flags |= RAW;
! (void) ioctl(0, TIOCSETN, (char *)&sb);
notc.t_stopc = -1;
notc.t_startc = -1;
! (void) ioctl(0, TIOCSETC, (char *)¬c);
}
if (!eight && (mark & TIOCPKT_DOSTOP)) {
! (void) ioctl(0, TIOCGETP, (char *)&sb);
sb.sg_flags &= ~RAW;
sb.sg_flags |= CBREAK;
! (void) ioctl(0, TIOCSETN, (char *)&sb);
notc.t_stopc = deftc.t_stopc;
notc.t_startc = deftc.t_startc;
! (void) ioctl(0, TIOCSETC, (char *)¬c);
}
if (mark & TIOCPKT_FLUSHWRITE) {
! (void) ioctl(1, TIOCFLUSH, (char *)&out);
for (;;) {
if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
***************
*** 495,499 ****
--- 542,551 ----
longjmp(rcvtop, 1);
}
+
/*
+ * 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
***************
*** 507,511 ****
* reader: read from remote: line -> 1
*/
! reader()
{
#if !defined(BSD) || BSD < 43
--- 559,564 ----
* reader: read from remote: line -> 1
*/
! reader(oldmask)
! int oldmask;
{
#if !defined(BSD) || BSD < 43
***************
*** 517,524 ****
char *bufp = rcvbuf;
! signal(SIGTTOU, SIG_IGN);
! fcntl(rem, F_SETOWN, pid);
ppid = getppid();
(void) setjmp(rcvtop);
for (;;) {
while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
--- 570,579 ----
char *bufp = rcvbuf;
! (void) signal(SIGTTOU, SIG_IGN);
! (void) signal(SIGURG, oob);
ppid = getppid();
+ (void) fcntl(rem, F_SETOWN, pid);
(void) setjmp(rcvtop);
+ (void) sigsetmask(oldmask);
for (;;) {
while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
***************
*** 554,559 ****
int lflags;
! ioctl(0, TIOCGETP, (char *)&sb);
! ioctl(0, TIOCLGET, (char *)&lflags);
switch (f) {
--- 609,614 ----
int lflags;
! (void) ioctl(0, TIOCGETP, (char *)&sb);
! (void) ioctl(0, TIOCLGET, (char *)&lflags);
switch (f) {
***************
*** 584,591 ****
return;
}
! ioctl(0, TIOCSLTC, (char *)ltc);
! ioctl(0, TIOCSETC, (char *)tc);
! ioctl(0, TIOCSETN, (char *)&sb);
! ioctl(0, TIOCLSET, (char *)&lflags);
}
--- 639,646 ----
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);
}
***************
*** 594,597 ****
--- 649,653 ----
char *f;
{
+
fprintf(stderr, f, a1, a2, a3, a4, a5);
fprintf(stderr, CRLF);
***************
*** 600,604 ****
lostpeer()
{
! signal(SIGPIPE, SIG_IGN);
prf("\007Connection closed.");
done(1);
--- 656,661 ----
lostpeer()
{
!
! (void) signal(SIGPIPE, SIG_IGN);
prf("\007Connection closed.");
done(1);
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list